2017-05-17 16:45:38 +02:00
package org.gcube.data.transfer.service.transfers.engine.impl ;
import java.io.File ;
import java.io.IOException ;
import java.nio.file.Files ;
2017-11-27 17:45:28 +01:00
import java.nio.file.LinkOption ;
import java.nio.file.attribute.BasicFileAttributes ;
2017-05-17 16:45:38 +02:00
import java.util.HashSet ;
import java.util.Set ;
import javax.inject.Singleton ;
2017-12-05 16:03:12 +01:00
import org.gcube.data.transfer.model.DeletionReport ;
2017-05-17 16:45:38 +02:00
import org.gcube.data.transfer.model.Destination ;
import org.gcube.data.transfer.model.DestinationClashPolicy ;
2017-11-27 17:45:28 +01:00
import org.gcube.data.transfer.model.RemoteFileDescriptor ;
2017-05-17 16:45:38 +02:00
import org.gcube.data.transfer.service.transfers.engine.PersistenceProvider ;
import org.gcube.data.transfer.service.transfers.engine.faults.DestinationAccessException ;
import org.gcube.smartgears.ContextProvider ;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration ;
import org.gcube.smartgears.context.application.ApplicationContext ;
import lombok.extern.slf4j.Slf4j ;
@Slf4j
@Singleton
public class PersistenceProviderImpl implements PersistenceProvider {
2017-11-27 17:45:28 +01:00
@Override
public File getPersistedFile ( String persistenceId , String subPath ) throws DestinationAccessException {
log . debug ( " Accessing <{}>/{} " , persistenceId , subPath ) ;
File persistenceFolder = getPersistenceFolderById ( persistenceId ) ;
return new File ( persistenceFolder . getAbsolutePath ( ) + " / " + subPath ) ;
}
2017-12-05 16:03:12 +01:00
2017-11-27 17:45:28 +01:00
@Override
public RemoteFileDescriptor getDescriptor ( String persistenceId , String subPath ) throws DestinationAccessException {
File file = getPersistedFile ( persistenceId , subPath ) ;
log . debug ( " Getting descriptor for {} " , file . getAbsolutePath ( ) ) ;
if ( ! file . exists ( ) ) throw new DestinationAccessException ( " Unable to find " + file . getAbsolutePath ( ) ) ;
RemoteFileDescriptor toReturn = new RemoteFileDescriptor ( ) ;
try {
BasicFileAttributes attributes = Files . readAttributes ( file . toPath ( ) , BasicFileAttributes . class , LinkOption . NOFOLLOW_LINKS ) ;
toReturn . setCreationDate ( attributes . creationTime ( ) . toMillis ( ) ) ;
toReturn . setLastUpdate ( attributes . lastModifiedTime ( ) . toMillis ( ) ) ;
toReturn . setSize ( attributes . size ( ) ) ;
} catch ( Throwable t ) {
log . warn ( " Unable to access attributes for {} " , file . getAbsolutePath ( ) , t ) ;
}
2017-12-05 16:03:12 +01:00
2017-11-27 17:45:28 +01:00
toReturn . setAbsolutePath ( file . getAbsolutePath ( ) ) ;
toReturn . setDirectory ( file . isDirectory ( ) ) ;
toReturn . setFilename ( file . getName ( ) ) ;
toReturn . setPersistenceId ( persistenceId ) ;
toReturn . setPath ( subPath ) ;
log . debug ( " Returning descriptor {} " , toReturn ) ;
return toReturn ;
}
2017-12-05 16:03:12 +01:00
2017-05-17 16:45:38 +02:00
@Override
public File getPersistenceFolderById ( String persistenceId ) throws DestinationAccessException {
File toReturn = null ;
log . debug ( " looking for persistence ID : {} " , persistenceId ) ;
if ( persistenceId . equalsIgnoreCase ( Destination . DEFAULT_PERSISTENCE_ID ) ) {
log . debug ( " Persistence ID is default " ) ;
ApplicationContext context = ContextProvider . get ( ) ;
toReturn = new File ( context . persistence ( ) . location ( ) ) ;
} else {
for ( ApplicationConfiguration config : ContextProvider . get ( ) . container ( ) . configuration ( ) . apps ( ) ) {
2017-05-19 18:03:11 +02:00
if ( config . context ( ) . equals ( persistenceId ) | | config . context ( ) . equals ( " / " + persistenceId ) ) {
2017-05-17 16:45:38 +02:00
log . debug ( " Found persistence ID {} " , persistenceId ) ;
toReturn = new File ( config . persistence ( ) . location ( ) ) ;
break ;
}
}
}
if ( toReturn = = null ) throw new DestinationAccessException ( " Persistence ID " + persistenceId + " not found. " ) ;
2017-12-05 16:03:12 +01:00
if ( ! toReturn . exists ( ) ) throw new DestinationAccessException ( " Persistence ID " + persistenceId + " , location " + toReturn . getAbsolutePath ( ) + " location doesn't exists. " ) ;
if ( ! toReturn . canWrite ( ) ) throw new DestinationAccessException ( " Cannot write to Persistence ID " + persistenceId + " , location " + toReturn . getAbsolutePath ( ) + " . " ) ;
if ( ! toReturn . isDirectory ( ) ) throw new DestinationAccessException ( " Persistence ID " + persistenceId + " , location " + toReturn . getAbsolutePath ( ) + " is a directory. " ) ;
if ( ! toReturn . canWrite ( ) ) throw new DestinationAccessException ( " Cannot write to Persistence ID " + persistenceId + " , location " + toReturn . getAbsolutePath ( ) + " . " ) ;
return toReturn ;
2017-05-17 16:45:38 +02:00
}
@Override
public Set < String > getAvaileblContextIds ( ) {
HashSet < String > toReturn = new HashSet < > ( ) ;
for ( ApplicationConfiguration config : ContextProvider . get ( ) . container ( ) . configuration ( ) . apps ( ) ) {
String toAddID = config . context ( ) ;
if ( toAddID . startsWith ( " / " ) ) toAddID = toAddID . substring ( 1 ) ;
toReturn . add ( toAddID ) ;
}
return toReturn ;
}
@Override
public File prepareDestination ( Destination dest ) throws DestinationAccessException {
File persistenceFolder = getPersistenceFolderById ( dest . getPersistenceId ( ) ) ;
if ( ! persistenceFolder . canWrite ( ) ) throw new DestinationAccessException ( " Cannot write to selecte persistenceFolder [ID : " + dest . getPersistenceId ( ) + " ] " ) ;
2017-05-19 18:03:11 +02:00
log . debug ( " Got Persistence folder PATH {}, ID {} " , persistenceFolder . getAbsolutePath ( ) , dest . getPersistenceId ( ) ) ;
2017-05-17 16:45:38 +02:00
String subFolderName = dest . getSubFolder ( ) ;
File subFolder = persistenceFolder ;
if ( subFolderName ! = null ) {
log . debug ( " Looking for subFolder : " + subFolder ) ;
if ( subFolderName . startsWith ( File . pathSeparator ) ) throw new DestinationAccessException ( " SubFolder cannot be absolute. " ) ;
// String[] pathItems=subFolderName.split(File.pathSeparator);
// for(String subPath:pathItems){
//// Set<String> existingFiles=new HashSet<String>(Arrays.asList(subFolder.list()));
// subFolder=new File(subFolder,subPath);
// if(subFolder.exists()){
// if(!subFolder.canRead()) throw new DestinationAccessException("Cannot write to "+subFolder.getAbsolutePath());
// }else if(dest.getCreateSubfolders()) subFolder.mkdir();
// else throw new DestinationAccessException("Destination subfolder {} not found. Set createSubFolder=true to create intermediary directories.");
// }
subFolder = new File ( persistenceFolder , subFolderName ) ;
if ( subFolder . exists ( ) ) {
if ( ! subFolder . canRead ( ) ) throw new DestinationAccessException ( " Cannot write to " + subFolder . getAbsolutePath ( ) ) ;
manageClash ( dest . getOnExistingSubFolder ( ) , subFolder ) ;
} else if ( dest . getCreateSubfolders ( ) ) subFolder . mkdirs ( ) ;
else throw new DestinationAccessException ( " SubFolder not found. Use createSubFolders=true to create it. " ) ;
}
File destination = new File ( subFolder , dest . getDestinationFileName ( ) ) ;
if ( destination . exists ( ) ) return manageClash ( dest . getOnExistingFileName ( ) , destination ) ;
else {
try {
destination . createNewFile ( ) ;
return destination ;
} catch ( IOException e ) {
throw new DestinationAccessException ( " Unable to create file " , e ) ;
}
}
}
2017-05-19 18:03:11 +02:00
public static final File manageClash ( DestinationClashPolicy policy , File clashing ) throws DestinationAccessException {
2017-05-17 16:45:38 +02:00
log . debug ( " Managing clash for {}, policy is {} " , clashing . getAbsolutePath ( ) , policy ) ;
boolean dir = clashing . isDirectory ( ) ;
try {
switch ( policy ) {
case ADD_SUFFIX : {
2017-05-19 18:03:11 +02:00
String clashingName = clashing . getName ( ) ;
String clashingBaseName = ( ! dir & & clashingName . contains ( " . " ) ) ? clashingName . substring ( 0 , clashingName . lastIndexOf ( " . " ) ) : clashingName ;
String destinationExtension = ( ! dir & & clashingName . contains ( " . " ) ) ? clashingName . substring ( clashingName . lastIndexOf ( " . " ) ) : " " ;
2017-12-05 16:03:12 +01:00
2017-05-17 16:45:38 +02:00
int counter = 1 ;
2017-05-19 18:03:11 +02:00
while ( clashing . exists ( ) ) {
clashing = new File ( clashing . getParentFile ( ) , clashingBaseName + " ( " + counter + " ) " + destinationExtension ) ;
2017-05-17 16:45:38 +02:00
counter + + ;
}
if ( dir ) clashing . mkdirs ( ) ;
else clashing . createNewFile ( ) ;
break ;
}
case FAIL : throw new DestinationAccessException ( " Found existing " + clashing . getAbsolutePath ( ) + " policy is " + policy ) ;
2017-11-13 14:38:38 +01:00
case REWRITE : {
deleteRecursively ( clashing ) ;
2017-05-17 16:45:38 +02:00
if ( dir ) clashing . mkdirs ( ) ;
else clashing . createNewFile ( ) ;
break ;
}
}
} catch ( IOException e ) {
throw new DestinationAccessException ( " Unable to rewrite existing destination " , e ) ;
}
return clashing ;
}
2017-12-05 16:03:12 +01:00
@Override
public DeletionReport delete ( String persistenceId , String subPath ) throws DestinationAccessException {
String toDeletePublicPath = persistenceId + " / " + subPath ;
File toDelete = getPersistedFile ( persistenceId , subPath ) ;
try {
log . warn ( " Going to DELETE {} aka {} " , toDelete . getAbsolutePath ( ) , toDeletePublicPath ) ;
deleteRecursively ( toDelete ) ;
return new DeletionReport ( toDeletePublicPath , toDelete . getAbsolutePath ( ) ) ;
} catch ( Throwable t ) {
throw new DestinationAccessException ( " Unable to delete " + toDeletePublicPath , t ) ;
}
}
public static final void deleteRecursively ( File toDelete ) throws IOException {
2017-11-13 14:38:38 +01:00
log . warn ( " Recursively deleting {} " , toDelete . getAbsolutePath ( ) ) ;
if ( toDelete . isDirectory ( ) ) {
for ( File child : toDelete . listFiles ( ) )
deleteRecursively ( child ) ;
} else Files . deleteIfExists ( toDelete . toPath ( ) ) ;
}
2017-05-17 16:45:38 +02:00
}