PackagerImpl.java
package esa.bscs.pds4.packager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import esa.bscs.pds4.packager.aip.AipBuilder;
import esa.bscs.pds4.packager.aip.ManifestInfo;
import esa.bscs.pds4.packager.aip.PackageInfo;
import esa.bscs.pds4.packager.exception.PackagerException;
import esa.bscs.pds4.packager.exception.PackagerMessage;
import esa.bscs.pds4.reader.Pds4Analyser;
import esa.bscs.pds4.reader.exception.Pds4Exception;
import esa.bscs.pds4.reader.model.Pds4Label;
import esa.bscs.pds4.validate.Pds4Validator;
import esa.bscs.pds4.validate.exception.ValidationException;
import esa.bscs.pds4.validate.model.ValidationMessage;
public class PackagerImpl implements Packager {
@Autowired(required=true)
private AipBuilder aipBuilder;
@Autowired(required=true)
private MessageSource messageSource;
@Autowired(required=true)
private Pds4Analyser analyser;
@Autowired(required=true)
private Pds4Validator validator;
@Override
public File pack(List<File> labelFiles) {
// Check input
if(labelFiles == null || labelFiles.isEmpty()) {
throw new IllegalArgumentException();
}
// Get metadata representation
final List<Pds4Label> pds4Labels = parseLabelFiles(labelFiles);
// Validate products
final List<ValidationMessage> messages = validator.validate(pds4Labels);
if(!messages.isEmpty()) {
throw new ValidationException(messages);
}
// Build archive information product
final PackageInfo packageInfo = aipBuilder.buildArchiveInformationProduct(pds4Labels);
// Generate tar.gz
return generatePackage(packageInfo);
}
private File generatePackage(PackageInfo packageInfo) {
// Generate tar.gz with the proper name in tmp directory
final String basename = packageInfo.getBasename();
final File result = new File(System.getProperty("java.io.tmpdir"), basename + ".tar.gz");
try (TarArchiveOutputStream stream = new TarArchiveOutputStream(new GzipCompressorOutputStream(new FileOutputStream(result)))) {
final Map<File, String> entries = packageInfo.getPackageEntries();
final ManifestInfo checksumInfo = packageInfo.getChecksumInfo();
final ManifestInfo transferInfo = packageInfo.getTransferInfo();
// Set stream to accept long paths (more than 100 bytes)
stream.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
// Add products to package
for(Map.Entry<File, String> entry : entries.entrySet()) {
try(InputStream inputStream = entry.getKey().toURI().toURL().openStream()) {
stream.putArchiveEntry(stream.createArchiveEntry(entry.getKey(), basename + "/" + entry.getValue()));
IOUtils.copy(inputStream, stream);
stream.closeArchiveEntry();
stream.flush();
}
}
// Add checksum manifest
TarArchiveEntry entry;
entry = (TarArchiveEntry) stream.createArchiveEntry(getFileFor(checksumInfo.getFilename()), basename + "/" + checksumInfo.getFilename());
entry.setSize(checksumInfo.getContent().getBytes().length);
stream.putArchiveEntry(entry);
stream.write(checksumInfo.getContent().getBytes());
stream.closeArchiveEntry();
stream.flush();
// Add transfer manifest
entry = (TarArchiveEntry) stream.createArchiveEntry(getFileFor(transferInfo.getFilename()), basename + "/" + transferInfo.getFilename());
entry.setSize(transferInfo.getContent().getBytes().length);
stream.putArchiveEntry(entry);
stream.write(transferInfo.getContent().getBytes());
stream.closeArchiveEntry();
stream.flush();
// Add delivery label
entry = (TarArchiveEntry) stream.createArchiveEntry(getFileFor(packageInfo.getFilename()), basename + "/" + packageInfo.getFilename());
entry.setSize(packageInfo.getContent().getBytes().length);
stream.putArchiveEntry(entry);
stream.write(packageInfo.getContent().getBytes());
stream.closeArchiveEntry();
stream.flush();
return result;
} catch(IOException e) {
throw new UncheckedIOException(e);
}
}
@SuppressWarnings("java:S1166")
private List<Pds4Label> parseLabelFiles(List<File> labelFiles) {
final List<Pds4Label> pds4Labels = new ArrayList<>();
final List<PackagerMessage> messages = new ArrayList<>();
for(File labelFile : labelFiles) {
try {
pds4Labels.add(analyser.analyse(labelFile.toURI().toURL()));
} catch(Pds4Exception e) {
final String name = e.getLabelLocation().getFile().contains("/") ? e.getLabelLocation().getFile().substring(e.getLabelLocation().getFile().lastIndexOf('/')) : e.getLabelLocation().getFile();
messages.add(new PackagerMessage("error.packager.parseLabel" , messageSource.getMessage("error.packager.parseLabel", new String[] {name, e.getCause().getMessage()}, Locale.getDefault())));
} catch(MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
if(!messages.isEmpty()) {
throw new PackagerException(messages);
}
return pds4Labels;
}
private File getFileFor(String filename) {
final Path path = Paths.get(new File(filename).toURI());
return path.toFile();
}
}