Skip to content

Commit

Permalink
MCR-3126 update OCFL
Browse files Browse the repository at this point in the history
* update ocfl-java version
* support file size
* support filekey
  • Loading branch information
Mewel committed Sep 3, 2024
1 parent b278c20 commit d6c8495
Show file tree
Hide file tree
Showing 23 changed files with 464 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.mycore.datamodel.niofs.MCRFileAttributes;
import org.mycore.datamodel.niofs.MCRVersionedPath;

// TODO javadoc
public class MCROCFLFileAttributes implements MCRFileAttributes<Object> {

private final FileTime creationTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
import java.nio.file.FileAlreadyExistsException;
Expand Down Expand Up @@ -97,7 +98,8 @@ void init() throws IOException {
.getSingleInstanceOfOrThrow(MCROCFLTransactionalTempFileStorage.class, tempFileClassProperty);
Files.createDirectories(this.localStorage.getRoot());
boolean remote = MCRConfiguration2.getBoolean(configurationPrefix + "FS.Remote").orElseThrow();
this.virtualObjectProvider = new MCROCFLVirtualObjectProvider(getRepository(), localStorage, remote);
this.virtualObjectProvider
= new MCROCFLVirtualObjectProvider(getRepository(), localStorage, remote);
} catch (Exception exception) {
throw new IOException("Unable to create MCROCFLFileSystem.", exception);
}
Expand Down Expand Up @@ -245,7 +247,7 @@ public void copy(MCRVersionedPath source, MCRVersionedPath target, CopyOption...
throw new NoSuchFileException(source.toString());
}
if (virtualSource.isDirectory(source)) {
createDirectory(target);
copyDirectory(target, options);
} else {
copyFile(source, target, options);
}
Expand Down Expand Up @@ -291,9 +293,6 @@ public void move(MCRVersionedPath source, MCRVersionedPath target, CopyOption...
delete(source);
}

/**
* {@inheritDoc}
*/
private void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOption... options) throws IOException {
MCROCFLVirtualObject virtualSource = virtualObjectProvider().get(source);
MCROCFLVirtualObject virtualTarget = virtualObjectProvider().getWritable(target);
Expand All @@ -304,11 +303,26 @@ private void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOpti
}
if (virtualSource.equals(virtualTarget)) {
// same virtual object
virtualSource.copyFile(source, target, options);
virtualSource.copy(source, target, options);
} else {
// different virtual object
virtualSource.copyFileToVirtualObject(virtualTarget, source, target, options);
virtualSource.externalCopy(virtualTarget, source, target, options);
}
}

private void copyDirectory(MCRVersionedPath target, CopyOption... options)
throws IOException {
MCROCFLVirtualObject virtualTarget = virtualObjectProvider().getWritable(target);
boolean targetExists = virtualTarget.exists(target);
boolean replaceExisting = Arrays.asList(options).contains(StandardCopyOption.REPLACE_EXISTING);
if (targetExists && replaceExisting) {
boolean targetIsDirectory = virtualTarget.isDirectory(target);
boolean targetDirectoryIsEmpty = virtualTarget.isDirectoryEmpty(target);
if (targetIsDirectory && !targetDirectoryIsEmpty) {
throw new DirectoryNotEmptyException(target.toString());
}
}
createDirectory(target);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,21 @@
import java.util.HashSet;
import java.util.Set;

import org.mycore.common.config.MCRConfiguration2;
import org.mycore.common.digest.MCRDigest;
import org.mycore.common.events.MCREvent;
import org.mycore.datamodel.niofs.MCRVersionedPath;
import org.mycore.ocfl.niofs.storage.MCROCFLTempFileStorage;
import org.mycore.ocfl.repository.MCROCFLRepository;

import io.ocfl.api.model.FileChangeHistory;
import io.ocfl.api.model.ObjectVersionId;
import io.ocfl.api.model.OcflObjectVersion;

/**
* Represents a virtual object stored locally in an OCFL repository.
* Represents a virtual object that is stored on the same drive as the OCFL repository. This provides the implementation
* direct access to the files of the OCFL repository when needed. For example a file can be accessed directly for read
* operations without copying it first to the local storage.
* <p>
* This class extends {@link MCROCFLVirtualObject} and provides implementations specific to local storage.
* It handles file operations such as copying, moving, and deleting files within the local file system,
Expand Down Expand Up @@ -90,7 +94,8 @@ public MCROCFLLocalVirtualObject(MCROCFLRepository repository, OcflObjectVersion
* @param directoryTracker the directory tracker.
*/
protected MCROCFLLocalVirtualObject(MCROCFLRepository repository, ObjectVersionId versionId,
OcflObjectVersion objectVersion, MCROCFLTempFileStorage localStorage, boolean readonly,
OcflObjectVersion objectVersion, MCROCFLTempFileStorage localStorage,
boolean readonly,
MCROCFLFileTracker<MCRVersionedPath, MCRDigest> fileTracker,
MCROCFLEmptyDirectoryTracker directoryTracker) {
super(repository, versionId, objectVersion, localStorage, readonly, fileTracker, directoryTracker);
Expand All @@ -100,7 +105,7 @@ protected MCROCFLLocalVirtualObject(MCROCFLRepository repository, ObjectVersionI
* {@inheritDoc}
*/
@Override
public void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOption... options) throws IOException {
public void copy(MCRVersionedPath source, MCRVersionedPath target, CopyOption... options) throws IOException {
checkPurged(source);
checkReadOnly();
boolean targetExists = exists(target);
Expand All @@ -119,7 +124,7 @@ public void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOptio
* {@inheritDoc}
*/
@Override
public void copyFileToVirtualObject(MCROCFLVirtualObject virtualTarget, MCRVersionedPath source,
public void externalCopy(MCROCFLVirtualObject virtualTarget, MCRVersionedPath source,
MCRVersionedPath target, CopyOption... options) throws IOException {
checkPurged(source);
virtualTarget.checkReadOnly();
Expand Down Expand Up @@ -172,39 +177,40 @@ protected SeekableByteChannel readOrWriteByteChannel(MCRVersionedPath path, Set<

@Override
public FileTime getModifiedTime(MCRVersionedPath path) throws IOException {
checkPurged(path);
checkExists(path);
Path physicalPath = toPhysicalPath(path);
return Files.readAttributes(physicalPath, BasicFileAttributes.class).lastModifiedTime();
}

@Override
public FileTime getAccessTime(MCRVersionedPath path) throws IOException {
checkPurged(path);
checkExists(path);
Path physicalPath = toPhysicalPath(path);
return Files.readAttributes(physicalPath, BasicFileAttributes.class).lastAccessTime();
}

@Override
public long getSize(MCRVersionedPath path) throws IOException {
checkPurged(path);
/**
* {@inheritDoc}
*/
public Path toPhysicalPath(MCRVersionedPath path) throws IOException {
checkExists(path);
if (isDirectory(path)) {
return 0;
if (this.localStorage.exists(path)) {
return this.localStorage.toPhysicalPath(path);
}
Path physicalPath = toPhysicalPath(path);
return Files.size(physicalPath);
FileChangeHistory changeHistory = getChangeHistory(path);
String storageRelativePath = changeHistory.getMostRecent().getStorageRelativePath();
return getLocalRepositoryPath().resolve(storageRelativePath);
}

@Override
public Object getFileKey(MCRVersionedPath path) throws IOException {
checkPurged(path);
checkExists(path);
// TODO the fileKey between the localstorage and the ocfl repository should always be the same
// this implementation is just a hack for testing
Path physicalPath = toPhysicalPath(path);
return Files.readAttributes(physicalPath, BasicFileAttributes.class).fileKey();
/**
* Returns the local OCFL repository path.
*
* @return the local repository path.
*/
protected Path getLocalRepositoryPath() {
return Path.of(MCRConfiguration2
.getString("MCR.OCFL.Repository." + repository.getId() + ".RepositoryRoot")
.orElseThrow());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ protected SeekableByteChannel readOrWriteByteChannel(MCRVersionedPath path, Set<
return seekableByteChannel;
}

/**
* {@inheritDoc}
*/
@Override
public FileTime getModifiedTime(MCRVersionedPath path) throws IOException {
checkExists(path);
Expand All @@ -129,9 +132,13 @@ public FileTime getModifiedTime(MCRVersionedPath path) throws IOException {
return FileTime.from(changeHistory.getMostRecent().getTimestamp().toInstant());
}

/**
* {@inheritDoc}
*/
@Override
public FileTime getAccessTime(MCRVersionedPath path) throws IOException {
checkExists(path);
// TODO is the localStorage check required? Or does the localVirtualObject take care of that
if (this.localStorage.exists(path)) {
Path physicalPath = this.localStorage.toPhysicalPath(path);
return Files.readAttributes(physicalPath, BasicFileAttributes.class).lastAccessTime();
Expand All @@ -140,37 +147,11 @@ public FileTime getAccessTime(MCRVersionedPath path) throws IOException {
return FileTime.from(changeHistory.getMostRecent().getTimestamp().toInstant());
}

@Override
public long getSize(MCRVersionedPath path) throws IOException {
checkExists(path);
if (isDirectory(path)) {
return 0;
}
// TODO right now we just copy and deliver from local storage
// in future versions we should use the database to get the size
localCopy(path);
//if(this.localStorage.exists(path)) {
Path physicalPath = this.localStorage.toPhysicalPath(path);
return Files.size(physicalPath);
//}
}

@Override
public Object getFileKey(MCRVersionedPath path) throws IOException {
checkExists(path);
// TODO rm this
localCopy(path);
// TODO the fileKey between the localstorage and the ocfl repository should always be the same
// this implementation is just a hack for testing
Path physicalPath = toPhysicalPath(path);
return Files.readAttributes(physicalPath, BasicFileAttributes.class).fileKey();
}

/**
* {@inheritDoc}
*/
@Override
public void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOption... options) throws IOException {
public void copy(MCRVersionedPath source, MCRVersionedPath target, CopyOption... options) throws IOException {
checkPurged(source);
checkReadOnly();
boolean targetExists = exists(target);
Expand All @@ -183,7 +164,7 @@ public void copyFile(MCRVersionedPath source, MCRVersionedPath target, CopyOptio
* {@inheritDoc}
*/
@Override
public void copyFileToVirtualObject(MCROCFLVirtualObject virtualTarget, MCRVersionedPath source,
public void externalCopy(MCROCFLVirtualObject virtualTarget, MCRVersionedPath source,
MCRVersionedPath target, CopyOption... options) throws IOException {
checkPurged(source);
virtualTarget.checkReadOnly();
Expand All @@ -202,7 +183,7 @@ public void copyFileToVirtualObject(MCROCFLVirtualObject virtualTarget, MCRVersi
public Path toPhysicalPath(MCRVersionedPath path) throws IOException {
checkExists(path);
localCopy(path);
return super.toPhysicalPath(path);
return this.localStorage.toPhysicalPath(path);
}

/**
Expand Down
Loading

0 comments on commit d6c8495

Please sign in to comment.