package org.alien4cloud.tosca.catalog.index;
import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import alien4cloud.images.IImageDAO;
import alien4cloud.images.ImageData;
import alien4cloud.images.exception.ImageUploadException;
import alien4cloud.model.common.Tag;
import org.alien4cloud.tosca.model.types.AbstractInheritableToscaType;
import alien4cloud.tosca.model.ArchiveRoot;
import alien4cloud.tosca.parser.ParsingError;
import alien4cloud.tosca.parser.ParsingErrorLevel;
import alien4cloud.tosca.parser.impl.ErrorCode;
/**
* Import images from CloudServiceArchive to ElasticSearch
*/
@Component
public class ArchiveImageLoader {
private static final String ALIEN_ICON_TAG = "icon";
private static final Pattern UUID_PATTERN = Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
@Inject
private IImageDAO imageDAO;
/**
* Import all images from the artifacts types in an archive.
*
* @param archiveFile The path to the root of the archive file.
* @param archiveRoot The parsed archive object that contains all the types and topologies.
* @param parsingErrors The list of parsing error in which to add errors in case there are (format error, file not found etc.)
*/
public void importImages(Path archiveFile, ArchiveRoot archiveRoot, List<ParsingError> parsingErrors) {
importImages(archiveFile, archiveRoot.getNodeTypes(), parsingErrors);
importImages(archiveFile, archiveRoot.getRelationshipTypes(), parsingErrors);
importImages(archiveFile, archiveRoot.getCapabilityTypes(), parsingErrors);
importImages(archiveFile, archiveRoot.getArtifactTypes(), parsingErrors);
}
private void importImages(Path archiveFile, Map<String, ? extends AbstractInheritableToscaType> toscaInheritableElement,
List<ParsingError> parsingErrors) {
if (toscaInheritableElement == null) {
return;
}
for (Map.Entry<String, ? extends AbstractInheritableToscaType> element : toscaInheritableElement.entrySet()) {
if (element.getValue().getTags() != null) {
List<Tag> tags = element.getValue().getTags();
Tag iconTag = ArchiveImageLoader.getIconTag(tags);
if (iconTag != null && !UUID_PATTERN.matcher(iconTag.getValue()).matches()) {
importImage(archiveFile, parsingErrors, iconTag);
}
}
}
}
private void importImage(Path archiveFile, List<ParsingError> parsingErrors, Tag iconTag) {
FileSystem csarFS = null;
Path iconPath = null;
try {
csarFS = FileSystems.newFileSystem(archiveFile, null);
iconPath = csarFS.getPath(iconTag.getValue());
if (!Files.isDirectory(iconPath)) {
String iconId = UUID.randomUUID().toString();
// Saving the image
ImageData imageData = new ImageData();
imageData.setData(Files.readAllBytes(iconPath));
imageData.setId(iconId);
imageDAO.writeImage(imageData);
// Replace the image uri by the indexed image ID
iconTag.setValue(iconId);
} else {
parsingErrors.add(new ParsingError(ParsingErrorLevel.WARNING, ErrorCode.INVALID_ICON_FORMAT, "Icon loading", null,
"Invalid icon format at path <" + iconPath + ">", null, iconPath.toString()));
}
} catch (NoSuchFileException | InvalidPathException e) {
parsingErrors.add(new ParsingError(ParsingErrorLevel.WARNING, ErrorCode.MISSING_FILE, "Icon loading", null,
"No icon file found at path <" + iconPath + ">", null, iconPath.toString()));
} catch (ImageUploadException e) {
parsingErrors.add(new ParsingError(ParsingErrorLevel.WARNING, ErrorCode.INVALID_ICON_FORMAT, "Icon loading", null,
"Invalid icon format at path <" + iconPath + ">", null, iconPath.toString()));
} catch (IOException e) {
parsingErrors.add(new ParsingError(ParsingErrorLevel.WARNING, ErrorCode.FAILED_TO_READ_FILE, "Icon loading", null,
"IO error while loading icon at path <" + iconPath + ">", null, iconPath.toString()));
}
}
/**
* Get the icon tag from a tag list.
*
* @param tags The list of tags in which to search for the icon tag.
* @return The icon tag or null if the tag cannot be found.
*/
public static Tag getIconTag(List<Tag> tags) {
if (tags == null) {
return null;
}
int iconTagIndex = tags.indexOf(new Tag(ALIEN_ICON_TAG, null));
if (iconTagIndex < 0) {
return null;
}
return tags.get(iconTagIndex);
}
}