package org.roda.core.migration.model; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.xmlbeans.XmlException; import org.roda.core.common.PremisV3Utils; import org.roda.core.common.iterables.CloseableIterable; import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.AlreadyExistsException; import org.roda.core.data.exceptions.AuthorizationDeniedException; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RODAException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.utils.URNUtils; import org.roda.core.data.v2.ip.StoragePath; import org.roda.core.data.v2.ip.metadata.PreservationMetadata; import org.roda.core.data.v2.ip.metadata.PreservationMetadata.PreservationMetadataType; import org.roda.core.data.v2.validation.ValidationException; import org.roda.core.migration.MigrationAction; import org.roda.core.model.utils.ModelUtils; import org.roda.core.storage.Binary; import org.roda.core.storage.ContentPayload; import org.roda.core.storage.DefaultStoragePath; import org.roda.core.storage.Resource; import org.roda.core.storage.StorageService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gov.loc.premis.v3.File; import gov.loc.premis.v3.ObjectIdentifierComplexType; public class PreservationMetadataFileToVersion2 implements MigrationAction<PreservationMetadata> { private static final Logger LOGGER = LoggerFactory.getLogger(PreservationMetadataFileToVersion2.class); @Override public void migrate(StorageService storage) throws RODAException { CloseableIterable<Resource> aips = null; try { aips = storage.listResourcesUnderDirectory(ModelUtils.getAIPContainerPath(), false); for (Resource aip : aips) { CloseableIterable<Resource> representations = null; try { representations = storage.listResourcesUnderDirectory( ModelUtils.getRepresentationsContainerPath(aip.getStoragePath().getName()), false); for (Resource representation : representations) { StoragePath pmPath = DefaultStoragePath.parse(representation.getStoragePath(), RodaConstants.STORAGE_DIRECTORY_METADATA, RodaConstants.STORAGE_DIRECTORY_PRESERVATION); CloseableIterable<Resource> pms = null; try { pms = storage.listResourcesUnderDirectory(pmPath, true); for (Resource pm : pms) { if (!pm.isDirectory() && pm instanceof Binary && pm.getStoragePath().getName() .startsWith(URNUtils.getPremisPrefix(PreservationMetadataType.FILE))) { Binary binary = (Binary) pm; migrate(storage, binary); } } } catch (NotFoundException | GenericException | AuthorizationDeniedException | RequestNotValidException e) { LOGGER.warn("Could not find preservation metadata files", e); } finally { IOUtils.closeQuietly(pms); } } } catch (NotFoundException | GenericException | AuthorizationDeniedException | RequestNotValidException e) { LOGGER.warn("Could not find representations", e); } finally { IOUtils.closeQuietly(representations); } } } catch (NotFoundException | GenericException | AuthorizationDeniedException | RequestNotValidException e) { LOGGER.warn("Could not find AIPs", e); } finally { IOUtils.closeQuietly(aips); } } private void migrate(StorageService storage, Binary binary) { InputStream inputStream = null; try { inputStream = binary.getContent().createInputStream(); StoragePath oldStoragePath = binary.getStoragePath(); File file = PremisV3Utils.binaryToFile(inputStream); String originalName = file.getOriginalName().getStringValue(); String value = null; for (ObjectIdentifierComplexType objectIdentifier : file.getObjectIdentifierArray()) { if (RodaConstants.PREMIS_IDENTIFIER_TYPE_URN .equals(objectIdentifier.getObjectIdentifierType().getStringValue())) { value = objectIdentifier.getObjectIdentifierValue(); value = value.substring(0, value.lastIndexOf(RodaConstants.URN_SEPARATOR) + 1); value += originalName; objectIdentifier.setObjectIdentifierValue(value); } } List<String> pathList = new ArrayList<String>(oldStoragePath.asList()); if (value != null) { pathList.remove(pathList.size() - 1); pathList.add(value + RodaConstants.PREMIS_SUFFIX); } StoragePath newStoragePath = DefaultStoragePath.parse(pathList); storage.move(storage, oldStoragePath, newStoragePath); ContentPayload newPremis = PremisV3Utils.fileToBinary(file); boolean asReference = false; boolean createIfNotExists = false; storage.updateBinaryContent(newStoragePath, newPremis, asReference, createIfNotExists); } catch (XmlException | GenericException | IOException | ValidationException | NotFoundException | RequestNotValidException | AuthorizationDeniedException | AlreadyExistsException e) { LOGGER.error("Could not migrate preservation metadata file {}", binary.getStoragePath(), e); } finally { IOUtils.closeQuietly(inputStream); } } @Override public boolean isToVersionValid(int toVersion) { return toVersion == 2; } }