/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/roda */ package org.roda.core.storage; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.io.IOUtils; import org.roda.core.common.iterables.CloseableIterable; 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.RequestNotValidException; import org.roda.core.data.v2.ip.StoragePath; /** * Storage Service related and independent utility class * * @author Hélder Silva <hsilva@keep.pt> * @author Luis Faria <lfaria@keep.pt> */ public final class StorageServiceUtils { /** * Private empty constructor */ private StorageServiceUtils() { } /** * Move resources from a given storage service/storage path to another storage * service/storage path * * @param fromService * source storage service * @param fromStoragePath * source storage path * @param toService * destination storage service * @param toStoragePath * destination storage path * @param rootEntity * class of the root entity * @throws AlreadyExistsException * @throws NotFoundException * @throws RequestNotValidException * @throws GenericException * @throws AuthorizationDeniedException */ public static void moveBetweenStorageServices(StorageService fromService, StoragePath fromStoragePath, StorageService toService, StoragePath toStoragePath, Class<? extends Entity> rootEntity) throws GenericException, RequestNotValidException, NotFoundException, AlreadyExistsException, AuthorizationDeniedException { copyOrMoveBetweenStorageServices(fromService, fromStoragePath, toService, toStoragePath, rootEntity, false); } /** * Copy resources from a given "storage service/storage path" to another * "storage service/storage path" * * @param fromService * source storage service * @param fromStoragePath * source storage path * @param toService * destination storage service * @param toStoragePath * destination storage path * @param rootEntity * class of the root entity * @throws AlreadyExistsException * @throws NotFoundException * @throws RequestNotValidException * @throws GenericException * @throws AuthorizationDeniedException */ public static void copyBetweenStorageServices(StorageService fromService, StoragePath fromStoragePath, StorageService toService, StoragePath toStoragePath, Class<? extends Entity> rootEntity) throws GenericException, RequestNotValidException, NotFoundException, AlreadyExistsException, AuthorizationDeniedException { copyOrMoveBetweenStorageServices(fromService, fromStoragePath, toService, toStoragePath, rootEntity, true); } private static void copyOrMoveBetweenStorageServices(StorageService fromService, StoragePath fromStoragePath, StorageService toService, StoragePath toStoragePath, Class<? extends Entity> rootEntity, boolean copy) throws GenericException, RequestNotValidException, NotFoundException, AlreadyExistsException, AuthorizationDeniedException { if (Container.class.isAssignableFrom(rootEntity)) { toService.createContainer(toStoragePath); boolean recursive = false; CloseableIterable<Resource> childResourcesIterator = fromService.listResourcesUnderContainer(fromStoragePath, recursive); iterateAndCopyOrMoveResources(fromService, fromStoragePath, toService, toStoragePath, childResourcesIterator, copy); if (!copy) { fromService.deleteContainer(fromStoragePath); } } else if (Directory.class.isAssignableFrom(rootEntity)) { toService.createDirectory(toStoragePath); boolean recursive = false; CloseableIterable<Resource> childResourcesIterator = fromService.listResourcesUnderDirectory(fromStoragePath, recursive); iterateAndCopyOrMoveResources(fromService, fromStoragePath, toService, toStoragePath, childResourcesIterator, copy); if (!copy) { fromService.deleteResource(fromStoragePath); } } else { Binary binary = fromService.getBinary(fromStoragePath); boolean asReference = false; toService.createBinary(toStoragePath, binary.getContent(), asReference); if (!copy) { fromService.deleteResource(fromStoragePath); } } } private static void iterateAndCopyOrMoveResources(StorageService fromService, StoragePath fromStoragePath, StorageService toService, StoragePath toStoragePath, CloseableIterable<Resource> childResourcesIterable, boolean copy) throws RequestNotValidException, AlreadyExistsException, GenericException, NotFoundException, AuthorizationDeniedException { Iterator<Resource> iterator = childResourcesIterable.iterator(); while (iterator.hasNext()) { Resource child = iterator.next(); if (copy) { toService.copy(fromService, child.getStoragePath(), extractToStoragePathChild(fromStoragePath, child.getStoragePath(), toStoragePath)); } else { toService.move(fromService, child.getStoragePath(), extractToStoragePathChild(fromStoragePath, child.getStoragePath(), toStoragePath)); } } IOUtils.closeQuietly(childResourcesIterable); } private static StoragePath extractToStoragePathChild(StoragePath fromStoragePath, StoragePath fromStoragePathChild, StoragePath toStoragePath) throws RequestNotValidException { List<String> fromChildRelativePath = fromStoragePathChild.asList().subList(fromStoragePath.asList().size(), fromStoragePathChild.asList().size()); List<String> toChildAbsolutePath = new ArrayList<>(toStoragePath.asList()); toChildAbsolutePath.addAll(fromChildRelativePath); return DefaultStoragePath.parse(toChildAbsolutePath); } }