/*
* Data Hub Service (DHuS) - For Space data distribution.
* Copyright (C) 2013,2014,2015 GAEL Systems
*
* This file is part of DHuS software sources.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.gael.dhus.service;
import fr.gael.dhus.database.dao.FileScannerDao;
import fr.gael.dhus.database.dao.UserDao;
import fr.gael.dhus.database.object.Collection;
import fr.gael.dhus.database.object.FileScanner;
import fr.gael.dhus.database.object.Product;
import fr.gael.dhus.database.object.User;
import fr.gael.dhus.datastore.exception.DataStoreAlreadyExistException;
import fr.gael.dhus.datastore.exception.DataStoreNotReadableProduct;
import fr.gael.dhus.datastore.scanner.Scanner;
import fr.gael.dhus.datastore.scanner.ScannerException;
import fr.gael.dhus.datastore.scanner.ScannerFactory;
import fr.gael.dhus.datastore.scanner.URLExt;
import fr.gael.dhus.service.exception.FileScannerNotModifiableException;
import fr.gael.dhus.service.exception.ProductNotAddedException;
import fr.gael.dhus.service.job.JobScheduler;
import fr.gael.dhus.util.UnZip;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Service
public class UploadService extends WebService
{
private static final Logger LOGGER = LogManager.getLogger(UploadService.class);
@Autowired
private SecurityService securityService;
@Autowired
private FileScannerDao fileScannerDao;
@Autowired
private UserDao userDao;
@Autowired
private ProductService productService;
@Autowired
private ScannerFactory scannerFactory;
@Autowired
private JobScheduler scheduler;
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
@Transactional (propagation=Propagation.REQUIRED)
public boolean addProduct (URL path, final User owner,
final List<Collection> collections) throws ProductNotAddedException
{
File product = null;
File newProduct = null;
try
{
LOGGER.info("Reading uploaded product : " + path.toExternalForm ());
product = new File(path.toURI ());
if (product.isFile () && UnZip.supported (product.getPath ()))
{
try
{
UnZip.unCompress (product.getPath (), product.getParent ());
}
catch (Exception e)
{
LOGGER.error("Failure during decompression.", e);
DataStoreNotReadableProduct dse =
new DataStoreNotReadableProduct ();
dse.initCause (e);
throw dse;
}
newProduct = new File(product.getParent ());
path = newProduct.toURI ().toURL ();
product.delete ();
Scanner scanner = scannerFactory.getScanner (
path.toExternalForm ());
scanner.setSupportedClasses (scannerFactory.getScannerSupport ());
scanner.getScanList ().simulate (false);
try
{
scanner.scan ();
}
catch (InterruptedException e)
{
throw new DataStoreNotReadableProduct (
"Process stopped by the user");
}
if (scanner.getScanList ().size () == 0)
{
throw new DataStoreNotReadableProduct ("No product recognized");
}
for (URLExt url: scanner.getScanList ())
{
Product p = productService.addProduct (
url.getUrl (), owner, null);
productService.processProduct (
p, owner, collections, scanner, null);
}
return true;
}
/* Case of one file product i.e. ENVISAT uploaded uncompressed */
else if (product.isFile ())
{
Product p = productService.addProduct (path, owner, null);
productService.processProduct (p, owner, collections, null, null);
return true;
}
else
{
throw new DataStoreNotReadableProduct (
"Uploaded product media not supported.");
}
}
catch (DataStoreAlreadyExistException e)
{
return false;
}
catch (DataStoreNotReadableProduct e)
{
if (product != null && product.exists ())
{
product.delete ();
}
if (newProduct != null && newProduct.exists ())
{
deleteDir(newProduct);
}
throw new ProductNotAddedException("Upload failed.", e);
}
catch (MalformedURLException e1)
{
LOGGER.warn("There was a problem accessing \""+path+"\"");
return false;
}
catch (URISyntaxException e1)
{
LOGGER.warn("There was a problem accessing \""+path+"\"");
return false;
}
}
private static boolean deleteDir(File dir)
{
if (dir.isDirectory())
{
String[] children = dir.list();
for (int i=0; i<children.length; i++)
{
boolean success = deleteDir(new File(dir, children[i]));
if (!success)
{
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public void processScan (final Long scan_id)
{
User user = securityService.getCurrentUser ();
try
{
scannerFactory.processScan (scan_id, user);
}
catch (ScannerException e)
{
LOGGER.info("Scanner id #" + scan_id + " not started: " +
e.getMessage ());
}
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public void stopScan (final Long scan_id)
{
try
{
scannerFactory.stopScan (scan_id);
}
catch (ScannerException e)
{
LOGGER.info("Scanner id #" + scan_id + " not started: " +
e.getMessage ());
}
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
@Transactional
public FileScanner addFileScanner (String url, String username,
String password, String pattern, Set<Collection> collections)
{
User user = securityService.getCurrentUser ();
return userDao.addFileScanner (user, url, username, password, pattern, "",
collections);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public void removeFileScanner (Long id)
{
User user = securityService.getCurrentUser ();
userDao.removeFileScanner (user, id);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
@Transactional
public Set<FileScanner> getFileScanners ()
{
User user = securityService.getCurrentUser ();
return userDao.getFileScanners (user);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public int countFileScanners ()
{
User user = securityService.getCurrentUser ();
return userDao.getFileScanners (user).size ();
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
@Transactional
public void updateFileScanner (Long id, String url, String username,
String password, String pattern, Set<Collection> collections)
{
FileScanner fileScanner = fileScannerDao.read (id);
if ((fileScanner == null) ||
(fileScanner.getStatus () == FileScanner.STATUS_RUNNING))
{
// Why ??
throw new FileScannerNotModifiableException (
"File scanner is running and cannot be modified.");
}
userDao.updateFileScanner (id, url, username, password, pattern, "",
collections);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
@Transactional
public void setFileScannerActive (Long id, boolean active)
{
FileScanner fileScanner = fileScannerDao.read (id);
if (fileScanner == null)
{
throw new FileScannerNotModifiableException (
"Scanner Id #" + id + " not found.");
}
userDao.setFileScannerActive (id, active);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public List<String> getFileScannerCollections (Long id)
{
return fileScannerDao.getScannerCollections (id);
}
@PreAuthorize ("hasRole('ROLE_UPLOAD')")
public Date getNextScheduleFileScanner() throws SchedulerException
{
return scheduler.getNextFileScannerJobSchedule ();
}
}