FileReferenceService.java
package de.dlr.shepard.context.references.file.services;
import de.dlr.shepard.auth.permission.services.PermissionsService;
import de.dlr.shepard.auth.security.AuthenticationContext;
import de.dlr.shepard.auth.users.entities.User;
import de.dlr.shepard.auth.users.services.UserService;
import de.dlr.shepard.common.exceptions.InvalidAuthException;
import de.dlr.shepard.common.exceptions.InvalidBodyException;
import de.dlr.shepard.common.exceptions.InvalidPathException;
import de.dlr.shepard.common.exceptions.InvalidRequestException;
import de.dlr.shepard.common.mongoDB.NamedInputStream;
import de.dlr.shepard.common.util.DateHelper;
import de.dlr.shepard.context.collection.services.CollectionService;
import de.dlr.shepard.context.collection.services.DataObjectService;
import de.dlr.shepard.context.references.IReferenceService;
import de.dlr.shepard.context.references.file.daos.FileReferenceDAO;
import de.dlr.shepard.context.references.file.entities.FileReference;
import de.dlr.shepard.context.references.file.io.FileReferenceIO;
import de.dlr.shepard.context.version.services.VersionService;
import de.dlr.shepard.data.file.daos.ShepardFileDAO;
import de.dlr.shepard.data.file.entities.FileContainer;
import de.dlr.shepard.data.file.entities.ShepardFile;
import de.dlr.shepard.data.file.services.FileContainerService;
import de.dlr.shepard.data.file.services.FileService;
import io.quarkus.logging.Log;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@RequestScoped
public class FileReferenceService implements IReferenceService<FileReference, FileReferenceIO> {
@Inject
FileReferenceDAO fileReferenceDAO;
@Inject
DataObjectService dataObjectService;
@Inject
FileContainerService fileContainerService;
@Inject
ShepardFileDAO fileDAO;
@Inject
VersionService versionService;
@Inject
DateHelper dateHelper;
@Inject
FileService fileService;
@Inject
PermissionsService permissionsService;
@Inject
CollectionService collectionService;
@Inject
AuthenticationContext authenticationContext;
@Inject
UserService userService;
/**
* Gets FileReference list for a given dataobject.
*
* @param collectionShepardId
* @param dataObjectShepardId
* @param versionUID the version UUID
* @return List<FileReference>
* @throws InvalidPathException If collection or dataobject cannot be found, or no association between dataobject and collection exists
* @throws InvalidAuthException If user has no read permissions on collection or dataobject specified by request path
*/
@Override
public List<FileReference> getAllReferencesByDataObjectId(
long collectionShepardId,
long dataObjectShepardId,
UUID versionUID
) {
dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId, versionUID);
List<FileReference> references = fileReferenceDAO.findByDataObjectShepardId(dataObjectShepardId);
return references;
}
/**
* Gets FileReference by shepard id.
*
* @param collectionShepardId
* @param dataObjectShepardId
* @param shepardId
* @param versionUID the version UUID
* @return FileReference
* @throws InvalidPathException If reference with Id does not exist or is deleted, or if collection or dataObject Id of path is not valid
* @throws InvalidAuthException If user has no read permissions on collection or dataobject specified by request path
*/
@Override
public FileReference getReference(
long collectionShepardId,
long dataObjectShepardId,
long shepardId,
UUID versionUID
) {
dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId, versionUID);
FileReference fileReference = fileReferenceDAO.findByShepardId(shepardId, versionUID);
if (fileReference == null || fileReference.isDeleted()) {
String errorMsg = String.format("ID ERROR - File Reference with id %s is null or deleted", shepardId);
Log.error(errorMsg);
throw new InvalidPathException(errorMsg);
}
if (
fileReference.getDataObject() == null || !fileReference.getDataObject().getShepardId().equals(dataObjectShepardId)
) {
String errorMsg = "ID ERROR - There is no association between dataObject and reference";
Log.error(errorMsg);
throw new InvalidPathException(errorMsg);
}
return fileReference;
}
/**
* Creates a new FileReference
*
* @param collectionShepardId
* @param dataObjectShepardId DataObject id for the reference to be created
* @param fileReference Reference object
* @return FileReference
* @throws InvalidPathException if collection or dataobject specified by their Ids are null or deleted
* @throws InvalidAuthException if user has no permission to edit referencing collection or no read permissions on referenced container
*/
@Override
public FileReference createReference(
long collectionShepardId,
long dataObjectShepardId,
FileReferenceIO fileReference
) {
var dataObject = dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId);
collectionService.assertIsAllowedToEditCollection(collectionShepardId);
User user = userService.getCurrentUser();
FileContainer container;
try {
container = fileContainerService.getContainer(fileReference.getFileContainerId());
} catch (InvalidPathException | InvalidAuthException ex) {
Log.error(ex.getMessage());
throw new InvalidBodyException(ex.getMessage());
}
var toCreate = new FileReference();
toCreate.setCreatedAt(dateHelper.getDate());
toCreate.setCreatedBy(user);
toCreate.setDataObject(dataObject);
toCreate.setName(fileReference.getName());
toCreate.setFileContainer(container);
// Get existing file
for (var oid : fileReference.getFileOids()) {
var file = fileDAO.find(container.getId(), oid);
if (file != null) {
toCreate.addFile(file);
} else {
Log.warnf("Could not find file with oid: %s", oid);
}
}
var created = fileReferenceDAO.createOrUpdate(toCreate);
created.setShepardId(created.getId());
created = fileReferenceDAO.createOrUpdate(created);
versionService.attachToVersionOfVersionableEntityAndReturnVersion(dataObject.getId(), created.getId());
return created;
}
/**
* Deletes the file reference.
*
* @param collectionShepardId
* @param dataObjectShepardId
* @param fileReferenceShepardId
* @throws InvalidPathException if collection or dataobject specified by their Ids are null or deleted
* @throws InvalidAuthException if user has no permissions to edit the collection, which the reference is assigned to
*/
@Override
public void deleteReference(long collectionShepardId, long dataObjectShepardId, long fileReferenceShepardId) {
FileReference fileReference = getReference(collectionShepardId, dataObjectShepardId, fileReferenceShepardId, null);
collectionService.assertIsAllowedToEditCollection(collectionShepardId);
User user = userService.getCurrentUser();
fileReference.setDeleted(true);
fileReference.setUpdatedBy(user);
fileReference.setUpdatedAt(dateHelper.getDate());
fileReferenceDAO.createOrUpdate(fileReference);
}
/**
* Returns list of ShepardFile.
*
* @param collectionShepardId
* @param dataObjectShepardId
* @param fileReferenceShepardId identifies the file reference
* @param versionUID
* @return list of shepard files
* @throws InvalidPathException if collection, dataobject or reference specified by their Ids are null or deleted
*/
public List<ShepardFile> getFiles(
long collectionShepardId,
long dataObjectShepardId,
long fileReferenceShepardId,
UUID versionUID
) {
FileReference reference = getReference(
collectionShepardId,
dataObjectShepardId,
fileReferenceShepardId,
versionUID
);
if (reference.getFileContainer() == null || reference.getFileContainer().isDeleted()) {
String errorMsg = String.format(
"Referenced FileContainer is not set or deleted in FileReference with id %s",
reference.getId()
);
Log.error(errorMsg);
throw new NotFoundException(errorMsg);
}
try {
fileContainerService.getContainer(reference.getFileContainer().getId());
} catch (InvalidPathException ex) {
Log.error(ex.getMessage());
throw new NotFoundException(ex.getMessage());
}
return reference.getFiles();
}
/**
* Returns a NamedInputStream of the specified file
*
* @param fileReferenceShepardId identifies the file reference
* @param oid identifies the actual file
* @param username the current user
* @return NamedInputStream
* @throws InvalidPathException when FileReference cannot be found due to invalid collection, dataobject or reference Ids
* @throws InvalidAuthException when the user is not authorized to access the container
* @throws NotFoundException when mongoDb is not able to find document container or file by mongoId or oid, or when Referenced file container is not accessible
* @throws InvalidRequestException when FileContainer is not accessible
*/
public NamedInputStream getPayload(
long collectionShepardId,
long dataObjectShepardId,
long fileReferenceShepardId,
String oid,
UUID versionUID
) {
FileReference reference = getReference(
collectionShepardId,
dataObjectShepardId,
fileReferenceShepardId,
versionUID
);
if (reference.getFileContainer() == null || reference.getFileContainer().isDeleted()) {
String errorMsg = String.format(
"FileContainer with id %s is not set or deleted in FileReference",
reference.getFileContainer()
);
Log.error(errorMsg);
throw new NotFoundException(errorMsg);
}
try {
// check that FileContainer is actually accessible and user has permissions to read from it
fileContainerService.getContainer(reference.getFileContainer().getId());
} catch (InvalidPathException e) {
Log.error(e.getMessage());
throw new NotFoundException(e.getMessage());
}
String mongoId = reference.getFileContainer().getMongoId();
return fileService.getPayload(mongoId, oid);
}
/**
* Returns a list of NamedInputStreams of all files in that reference
*
* Returns empty input streams if referenced file container is not accessible.
*
* @param collectionShepardId
* @param dataObjectShepardId
* @param fileReferenceShepardId identifies the file reference
* @return list of NamedInputStreams
* @throws InvalidPathException when FileReference cannot be found due to invalid collection, dataobject or reference Ids
* @throws NotFoundException when container is not accessible
* @throws InvalidAuthException when the user is not authorized to access the container
*/
public List<NamedInputStream> getAllPayloads(
long collectionShepardId,
long dataObjectShepardId,
long fileReferenceShepardId
) {
FileReference reference = getReference(collectionShepardId, dataObjectShepardId, fileReferenceShepardId, null);
if (reference.getFileContainer() == null || reference.getFileContainer().isDeleted()) {
String errorMsg = String.format(
"Referenced FileContainer is not set or deleted in FileReference with id %s",
reference.getId()
);
Log.error(errorMsg);
throw new NotFoundException(errorMsg);
}
try {
// check that referenced container is actually accessible
fileContainerService.getContainer(reference.getFileContainer().getId());
} catch (InvalidPathException ex) {
throw new NotFoundException(ex.getMessage());
}
List<ShepardFile> files = reference.getFiles();
var result = new ArrayList<NamedInputStream>(files.size());
for (var file : files) {
NamedInputStream nis;
try {
nis = fileService.getPayload(reference.getFileContainer().getMongoId(), file.getOid());
result.add(nis);
} catch (NotFoundException e) {
result.add(new NamedInputStream(file.getOid(), null, file.getFilename(), 0L));
}
}
return result;
}
}