/******************************************************************************* | |
* Copyright (c) 2020 Contributors to the Eclipse Foundation | |
* | |
* See the NOTICE file(s) distributed with this work for additional | |
* information regarding copyright ownership. | |
* | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v. 2.0 which is available at | |
* http://www.eclipse.org/legal/epl-2.0. | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
*******************************************************************************/ | |
package org.eclipse.mdm.api.atfxadapter.filetransfer; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.time.Duration; | |
import java.time.LocalTime; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.UUID; | |
import java.util.concurrent.atomic.AtomicLong; | |
import java.util.stream.Collectors; | |
import org.eclipse.mdm.api.base.file.FileService; | |
import org.eclipse.mdm.api.base.model.Entity; | |
import org.eclipse.mdm.api.base.model.FileLink; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
/** | |
* @author akn | |
* | |
*/ | |
public class ATFXFileService implements FileService { | |
private static final Logger LOGGER = LoggerFactory.getLogger(ATFXFileService.class); | |
private final Path parentDirectory; | |
public ATFXFileService(File parentDirectory) { | |
this.parentDirectory = parentDirectory.toPath(); | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#downloadSequential(org.eclipse.mdm. | |
* api.base.model.Entity, java.nio.file.Path, java.util.Collection, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public void downloadSequential(Entity entity, Path target, Collection<FileLink> fileLinks, | |
ProgressListener progressListener) throws IOException { | |
Map<String, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isRemote) | |
.collect(Collectors.groupingBy(FileLink::getRemotePath)); | |
long totalSize = calculateDownloadSize(groups); | |
final AtomicLong transferred = new AtomicLong(); | |
LocalTime start = LocalTime.now(); | |
UUID id = UUID.randomUUID(); | |
LOGGER.debug("Sequential download of {} file(s) with id '{}' started.", groups.size(), id); | |
for (List<FileLink> group : groups.values()) { | |
FileLink fileLink = group.get(0); | |
download(entity, target, fileLink, (b, p) -> { | |
double tranferredBytes = transferred.addAndGet(b); | |
if (progressListener != null) { | |
progressListener.progress(b, (float) (tranferredBytes / totalSize)); | |
} | |
}); | |
for (FileLink other : group.subList(1, group.size())) { | |
other.setLocalStream(fileLink.getLocalStream()); | |
} | |
} | |
LOGGER.debug("Sequential download with id '{}' finished in {}.", id, Duration.between(start, LocalTime.now())); | |
} | |
private long calculateDownloadSize(Map<String, List<FileLink>> groups) { | |
List<FileLink> links = groups.values().stream().map(l -> l.get(0)).collect(Collectors.toList()); | |
long totalSize = 0; | |
for (FileLink fileLink : links) { | |
File f = new File(fileLink.getRemotePath()); | |
// overflow may occur in case of total size exceeds 9223 PB! | |
totalSize = Math.addExact(totalSize, f.length()); | |
} | |
return totalSize; | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#downloadParallel(org.eclipse.mdm. | |
* api.base.model.Entity, java.nio.file.Path, java.util.Collection, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public void downloadParallel(Entity entity, Path target, Collection<FileLink> fileLinks, | |
ProgressListener progressListener) throws IOException { | |
// TODO Auto-generated method stub | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#download(org.eclipse.mdm.api.base. | |
* model.Entity, java.nio.file.Path, org.eclipse.mdm.api.base.model.FileLink, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public void download(Entity entity, Path target, FileLink fileLink, ProgressListener progressListener) | |
throws IOException { | |
if (Files.exists(target)) { | |
if (!Files.isDirectory(target)) { | |
throw new IllegalArgumentException("Target path is not a directory."); | |
} | |
} else { | |
Files.createDirectory(target); | |
} | |
try (InputStream inputStream = openStream(entity, fileLink)) { | |
Path absolutePath = target.resolve(fileLink.getFileName()).toAbsolutePath(); | |
String remotePath = fileLink.getRemotePath(); | |
LOGGER.debug("Starting download of file '{}' to '{}'.", remotePath, absolutePath); | |
LocalTime start = LocalTime.now(); | |
Files.copy(inputStream, absolutePath); | |
LOGGER.debug("File '{}' successfully downloaded in {} to '{}'.", remotePath, | |
Duration.between(start, LocalTime.now()), absolutePath); | |
} | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#openStream(org.eclipse.mdm.api.base | |
* .model.Entity, org.eclipse.mdm.api.base.model.FileLink, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public InputStream openStream(Entity entity, FileLink fileLink, ProgressListener progressListener) | |
throws IOException { | |
return new FileInputStream(parentDirectory.resolve(fileLink.getRemotePath()).toFile()); | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#loadSize(org.eclipse.mdm.api.base. | |
* model.Entity, org.eclipse.mdm.api.base.model.FileLink) | |
*/ | |
@Override | |
public void loadSize(Entity entity, FileLink fileLink) throws IOException { | |
// TODO Auto-generated method stub | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#uploadSequential(org.eclipse.mdm. | |
* api.base.model.Entity, java.util.Collection, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public void uploadSequential(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener) | |
throws IOException { | |
// TODO Auto-generated method stub | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#uploadParallel(org.eclipse.mdm.api. | |
* base.model.Entity, java.util.Collection, | |
* org.eclipse.mdm.api.base.file.FileService.ProgressListener) | |
*/ | |
@Override | |
public void uploadParallel(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener) | |
throws IOException { | |
// TODO Auto-generated method stub | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#delete(org.eclipse.mdm.api.base. | |
* model.Entity, java.util.Collection) | |
*/ | |
@Override | |
public void delete(Entity entity, Collection<FileLink> fileLinks) { | |
// TODO Auto-generated method stub | |
} | |
/* | |
* (non-Javadoc) | |
* | |
* @see | |
* org.eclipse.mdm.api.base.file.FileService#delete(org.eclipse.mdm.api.base. | |
* model.Entity, org.eclipse.mdm.api.base.model.FileLink) | |
*/ | |
@Override | |
public void delete(Entity entity, FileLink fileLink) { | |
// TODO Auto-generated method stub | |
} | |
} |