diff --git a/conf/core/jobs.csv b/conf/core/jobs.csv index a1c4c4c8da91e1088fcb82bef7d3ba139e2ffe52..e2fe974b4304e594e58ce62599b36d389885ddf7 100644 --- a/conf/core/jobs.csv +++ b/conf/core/jobs.csv @@ -77,6 +77,17 @@ 0,9,UPDATE,CheckTargetPathValid,ERROR 0,9,UPDATE,SetImpToFix,ERROR +## link rules +0,10,INSERT,CheckNamePresent,WARN +0,10,INSERT,MatchFileProp,ERROR +0,10,INSERT,CheckTargetPathValid,ERROR +0,10,INSERT,SetImpToFix,ERROR + +0,10,UPDATE,CheckNamePresent,WARN +0,10,UPDATE,MatchFileProp,ERROR +0,10,UPDATE,CheckTargetPathValid,ERROR +0,10,UPDATE,SetImpToFix,ERROR + ## property rules 0,4,INSERT,CheckDatatypePresent,ERROR 0,4,UPDATE,CheckDatatypePresent,ERROR diff --git a/src/main/java/org/caosdb/server/database/DatabaseUtils.java b/src/main/java/org/caosdb/server/database/DatabaseUtils.java index ad8810418015deebc81a587f30ce904ac3401a4a..d31f10fc0e29b55b223b454c6848b1ea6c7ba0b7 100644 --- a/src/main/java/org/caosdb/server/database/DatabaseUtils.java +++ b/src/main/java/org/caosdb/server/database/DatabaseUtils.java @@ -224,7 +224,7 @@ public class DatabaseUtils { throws SQLException { final String key = bytes2UTF8(rs.getBytes("FileKey")); if (key != null) { - // ret.fileParentId = rs.getInt("FileParentID"); + ret.fileParentId = rs.getInt("FileParentID"); ret.filePath = new Path(bytes2UTF8(rs.getBytes("FilePath"))); ret.fileSize = rs.getLong("FileSize"); if (rs.wasNull()) { @@ -245,6 +245,10 @@ public class DatabaseUtils { } ret.fileStorageId = bytes2UTF8(rs.getBytes("FileStorageID")); ret.fileKey = key; + + if (ret.fileType == ObjectType.LINK) { + ret.linkTarget = rs.getInt("LinkTarget"); + } } } diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetVirtualFSO.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetVirtualFSO.java index 71b0ba1e99789e9fd08d7d1ca5abd5639baf2939..21f8f0990a34c084e6d30f59e709cf2dfdece90d 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetVirtualFSO.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLGetVirtualFSO.java @@ -17,9 +17,7 @@ public class MySQLGetVirtualFSO extends MySQLTransaction implements GetVirtualFS super(access); } - public static final String STMT_GET_FSO = - "SELECT 'SHA-512' AS FileHashAlgo, file_id AS FileId, " - + /*parent_directory AS FileParentID,*/ " path AS FilePath, size AS FileSize, hex(hash) AS FileHash, checked_timestamp AS FileHashChecked, mimetype AS FileMimeType, file_storage_id AS FileStorageID, file_key AS FileKey FROM files WHERE file_storage_id = ? AND file_key = ?"; + public static final String STMT_GET_FSO = "call retrieveFSODescriptor(?, ?)"; @Override public VirtualFSODescriptorInterface execute(String fileStorageId, String key) { diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertFSODescriptor.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertFSODescriptor.java index 305bb6c41a41ab1719c55f1eaaac30089e240e68..3c38279e6ff6896c92b7956cf4386b017cd10fe3 100644 --- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertFSODescriptor.java +++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLInsertFSODescriptor.java @@ -17,7 +17,7 @@ public class MySQLInsertFSODescriptor extends MySQLTransaction implements Insert } public static final String STMT_INSERT_FILE_PROPERTIES = - "call insertFSODescriptor(?,?,?, ?,?,?, ?,?,?, ?)"; + "call insertFSODescriptor(?,?,?, ?,?,?, ?,?,?, ?,?)"; @Override public void insertFSODescriptor(final SparseEntity entity) { @@ -56,6 +56,11 @@ public class MySQLInsertFSODescriptor extends MySQLTransaction implements Insert } insertFilePropsStmt.setString(9, entity.fileStorageId); insertFilePropsStmt.setString(10, entity.fileKey); + if (entity.linkTarget != null) { + insertFilePropsStmt.setInt(11, entity.linkTarget); + } else { + insertFilePropsStmt.setNull(11, Types.INTEGER); + } insertFilePropsStmt.execute(); } } catch (final SQLIntegrityConstraintViolationException exc) { diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/CheckTargetPath.java b/src/main/java/org/caosdb/server/database/backend/transaction/CheckTargetPath.java index e72b4556c16b1e5411d71763f95674e080f189c9..274dd0df43f2d1ab7807c10251ba99befbf3644f 100644 --- a/src/main/java/org/caosdb/server/database/backend/transaction/CheckTargetPath.java +++ b/src/main/java/org/caosdb/server/database/backend/transaction/CheckTargetPath.java @@ -2,9 +2,11 @@ package org.caosdb.server.database.backend.transaction; import org.caosdb.server.database.BackendTransaction; import org.caosdb.server.database.exceptions.EntityDoesNotExistException; +import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.Message; import org.caosdb.server.entity.container.TransactionContainer; +import org.caosdb.server.filesystem.FileSystem.ObjectType; import org.caosdb.server.filesystem.Path; import org.caosdb.server.filesystem.VirtualFSODescriptorInterface; import org.caosdb.server.utils.ServerMessages; @@ -42,6 +44,29 @@ public class CheckTargetPath extends BackendTransaction { checkNastyPath(entity.getFSODescriptor().getPath()); checkOwner(entity); checkParentExists(entity, container); + checkLinkTarget(entity, container); + } + + private void checkLinkTarget(EntityInterface entity, TransactionContainer container) { + if (entity.getFSODescriptor().getObjectType() != ObjectType.LINK) { + return; + } + + EntityID linkTarget = entity.getFSODescriptor().getLinkTarget(); + + EntityInterface linkTargetEntity = container.getEntityById(linkTarget); + if (linkTargetEntity == null) { + RetrieveSparseEntity t = new RetrieveSparseEntity(linkTarget, null); + linkTargetEntity = execute(t).getEntity(); + } + + if (linkTargetEntity.getRole().hasFSODescriptor()) { + linkTarget.link(linkTargetEntity.getId()); + entity.getFSODescriptor().setLinkTargetPath(linkTargetEntity.getFSODescriptor().getPath()); + + } else { + // TODO(tf) throw something + } } private void checkParentExists(EntityInterface entity, TransactionContainer container) diff --git a/src/main/java/org/caosdb/server/database/backend/transaction/ListDirectory.java b/src/main/java/org/caosdb/server/database/backend/transaction/ListDirectory.java new file mode 100644 index 0000000000000000000000000000000000000000..4050d55a90b3a2c028d934f7c0629513eaefd477 --- /dev/null +++ b/src/main/java/org/caosdb/server/database/backend/transaction/ListDirectory.java @@ -0,0 +1,34 @@ +package org.caosdb.server.database.backend.transaction; + +import java.util.LinkedList; +import java.util.List; +import org.caosdb.server.database.BackendTransaction; +import org.caosdb.server.database.backend.interfaces.GetFilesInDirectoryImpl; +import org.caosdb.server.database.proto.SparseEntity; +import org.caosdb.server.entity.EntityID; +import org.caosdb.server.filesystem.FSODescriptor; +import org.caosdb.server.filesystem.VirtualFSODescriptorInterface; + +public class ListDirectory extends BackendTransaction { + + private EntityID id; + private List<VirtualFSODescriptorInterface> children = new LinkedList<>(); + + public ListDirectory(EntityID id) { + this.id = id; + } + + @Override + protected void execute() { + GetFilesInDirectoryImpl t = getImplementation(GetFilesInDirectoryImpl.class); + List<SparseEntity> spes = t.execute(id); + + for (SparseEntity spe : spes) { + children.add(new FSODescriptor(spe)); + } + } + + public List<VirtualFSODescriptorInterface> getChildren() { + return children; + } +} diff --git a/src/main/java/org/caosdb/server/database/proto/SparseEntity.java b/src/main/java/org/caosdb/server/database/proto/SparseEntity.java index e99cdd8096bfeb47c838ed365c8c7bda563e7b28..4cedd8765b65a5c45166da473e8eb680f828ee59 100644 --- a/src/main/java/org/caosdb/server/database/proto/SparseEntity.java +++ b/src/main/java/org/caosdb/server/database/proto/SparseEntity.java @@ -50,6 +50,7 @@ public class SparseEntity extends VerySparseEntity { public String versionId = null; public Long versionSeconds = null; public Integer versionNanos = null; + public Integer linkTarget = null; @Override public String toString() { @@ -68,6 +69,7 @@ public class SparseEntity extends VerySparseEntity { .append(this.fileMimeType) .append(this.fileType) .append(this.fileParentId) + .append(this.linkTarget) .append(this.versionId) .append(this.versionSeconds) .append(this.versionNanos) diff --git a/src/main/java/org/caosdb/server/entity/Entity.java b/src/main/java/org/caosdb/server/entity/Entity.java index 317aea4dfc9e15e2115817621a455f083ff3d5b5..04237c31cef8e319a4a6207ee24d919836f2bd86 100644 --- a/src/main/java/org/caosdb/server/entity/Entity.java +++ b/src/main/java/org/caosdb/server/entity/Entity.java @@ -56,6 +56,7 @@ import org.caosdb.server.entity.xml.ToElementStrategy; import org.caosdb.server.entity.xml.ToElementable; import org.caosdb.server.filesystem.FSODescriptor; import org.caosdb.server.filesystem.FileSystem; +import org.caosdb.server.filesystem.FileSystem.ObjectType; import org.caosdb.server.filesystem.Hash; import org.caosdb.server.filesystem.Hasher; import org.caosdb.server.filesystem.Path; @@ -385,6 +386,9 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa if (getFSODescriptor().getParentDirectoryID() != null) { ret.fileParentId = getFSODescriptor().getParentDirectoryID().toInteger(); } + if (ret.fileType == ObjectType.LINK && getFSODescriptor().getLinkTarget() != null) { + ret.linkTarget = getFSODescriptor().getLinkTarget().toInteger(); + } } return ret; } @@ -805,12 +809,23 @@ public abstract class Entity extends AbstractObservable implements EntityInterfa tmpIdentifier = tmpIdentifier.substring(0, tmpIdentifier.length() - 1); } + // Parse LINKTARGET + Integer linkTarget = null; + if (element.getAttribute("linktarget") != null + && !element.getAttributeValue("linktarget").isBlank()) { + linkTarget = Integer.parseInt(element.getAttributeValue("linktarget")); + } + // Store PATH, HASH, SIZE, TMPIDENTIFYER if (tmpIdentifier != null || checksum != null || path != null || size != null) { // legacy clients (which use this api) always use sha512. Hash hash = Hash.create(checksum, 0, Hasher.Default); if (getRole() == Role.Directory) { setFSODescriptor(FSODescriptor.createDir(FileSystem.DEFAULT_BACKEND, new Path(path))); + } else if (getRole() == Role.Link) { + setFSODescriptor( + FSODescriptor.createLink( + FileSystem.DEFAULT_BACKEND, new Path(path), new EntityID(linkTarget))); } else { setFSODescriptor( new FSODescriptor( diff --git a/src/main/java/org/caosdb/server/entity/Role.java b/src/main/java/org/caosdb/server/entity/Role.java index 992ddc6e6bbc8c8cfbc702667afce13a0a0ba93b..0e98e2c72c810dff337a476516ef8baddae9778c 100644 --- a/src/main/java/org/caosdb/server/entity/Role.java +++ b/src/main/java/org/caosdb/server/entity/Role.java @@ -83,6 +83,6 @@ public enum Role { } public boolean hasFSODescriptor() { - return this == File || this == Directory; + return this == File || this == Directory || this == Link; } } diff --git a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java index a8c3e6a832848903884edda270e003a0c0dd6feb..397af673f438beba0620c3fa412ed3fd613f524b 100644 --- a/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/EntityByIdContainer.java @@ -22,7 +22,7 @@ */ package org.caosdb.server.entity.container; -import java.util.HashMap; +import java.util.Map; import org.apache.shiro.subject.Subject; import org.caosdb.server.entity.EntityID; @@ -33,7 +33,7 @@ public abstract class EntityByIdContainer extends TransactionContainer { final Subject user, final Long timestamp, final String srid, - final HashMap<String, String> flags) { + final Map<String, String> flags) { super(user, timestamp, srid, flags); } diff --git a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java index bc0da7c1de2bb876551d29ad7daffb50494f9720..24a2617865697c73ef5d8710f201930b7cac9f4e 100644 --- a/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/RetrieveContainer.java @@ -22,7 +22,7 @@ */ package org.caosdb.server.entity.container; -import java.util.HashMap; +import java.util.Map; import org.apache.shiro.subject.Subject; import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.RetrieveEntity; @@ -35,7 +35,7 @@ public class RetrieveContainer extends EntityByIdContainer { final Subject user, final Long timestamp, final String srid, - final HashMap<String, String> flags) { + final Map<String, String> flags) { super(user, timestamp, srid, flags); } diff --git a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java index 52fd675f4816f2df16ef68722bef572a807a5348..89ff91d4e56574fe137968ddd344b547df442817 100644 --- a/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/TransactionContainer.java @@ -25,6 +25,7 @@ package org.caosdb.server.entity.container; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import org.apache.shiro.subject.Subject; import org.caosdb.server.CaosDBServer; import org.caosdb.server.database.misc.TransactionBenchmark; @@ -60,7 +61,7 @@ public class TransactionContainer extends Container<EntityInterface> final Subject user, final Long timestamp, final String srid, - final HashMap<String, String> flags) { + final Map<String, String> flags) { this(user, timestamp, srid); setFlags(flags); } @@ -91,9 +92,9 @@ public class TransactionContainer extends Container<EntityInterface> this.messages.add(m); } - private HashMap<String, String> flags = null; + private Map<String, String> flags = null; - public HashMap<String, String> getFlags() { + public Map<String, String> getFlags() { return this.flags; } @@ -156,7 +157,7 @@ public class TransactionContainer extends Container<EntityInterface> return null; } - public void setFlags(final HashMap<String, String> flags) { + public void setFlags(final Map<String, String> flags) { this.flags = flags; } diff --git a/src/main/java/org/caosdb/server/entity/container/WritableContainer.java b/src/main/java/org/caosdb/server/entity/container/WritableContainer.java index dc88de5731c6948314f7594c14ae3e2d621814fd..bb193a8105b690b5f195d2f9fd694c2ab614518b 100644 --- a/src/main/java/org/caosdb/server/entity/container/WritableContainer.java +++ b/src/main/java/org/caosdb/server/entity/container/WritableContainer.java @@ -21,7 +21,7 @@ */ package org.caosdb.server.entity.container; -import java.util.HashMap; +import java.util.Map; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; @@ -32,7 +32,7 @@ public class WritableContainer extends TransactionContainer { final Subject user, final Long timestamp, final String srid, - final HashMap<String, String> flags) { + final Map<String, String> flags) { super(user, timestamp, srid, flags); } diff --git a/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java b/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java index 26122ba414133da7a5bfa5981f6c68f684028997..92779f2b2dd7f04d5a6fd2ee5d03db685996c303 100644 --- a/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java +++ b/src/main/java/org/caosdb/server/entity/xml/FileToElementStrategy.java @@ -23,6 +23,7 @@ package org.caosdb.server.entity.xml; import org.caosdb.server.entity.EntityInterface; +import org.caosdb.server.filesystem.FileSystem.ObjectType; import org.jdom2.Attribute; import org.jdom2.Element; @@ -48,6 +49,11 @@ public class FileToElementStrategy extends EntityToElementStrategy { element.setAttribute( new Attribute("size", Long.toString(entity.getFSODescriptor().getSize()))); } + if (serializeFieldStrategy.isToBeSet("linktarget") + && entity.getFSODescriptor().getObjectType() == ObjectType.LINK + && entity.getFSODescriptor().getLinkTarget() != null) { + element.setAttribute("linktarget", entity.getFSODescriptor().getLinkTarget().toString()); + } } return element; } diff --git a/src/main/java/org/caosdb/server/filesystem/FSODescriptor.java b/src/main/java/org/caosdb/server/filesystem/FSODescriptor.java index 5290f8698e828cd5da4a6b953690a9710834847f..19b1c829accfc0a4fd881024f437a5ac9e3af4eb 100644 --- a/src/main/java/org/caosdb/server/filesystem/FSODescriptor.java +++ b/src/main/java/org/caosdb/server/filesystem/FSODescriptor.java @@ -33,6 +33,7 @@ public class FSODescriptor implements VirtualFSODescriptorInterface { protected EntityStatus status = null; protected Hash hash = null; protected Path path = null; + protected Path linkTargetPath = null; protected Long size = null; protected String tmpIdentifier = null; protected EntityID entityId = new EntityID(); @@ -41,6 +42,7 @@ public class FSODescriptor implements VirtualFSODescriptorInterface { protected EntityID parentDirectory = null; protected List<VirtualFSODescriptorInterface> children; private RealFSODescriptorInterface twin; + private EntityID linkTarget = null; public FSODescriptor( final String fileStorageId, @@ -80,6 +82,7 @@ public class FSODescriptor implements VirtualFSODescriptorInterface { this.type = spe.fileType; this.mimeType = spe.fileMimeType; this.parentDirectory = new EntityID(spe.fileParentId); + this.linkTarget = new EntityID(spe.linkTarget); } public FSODescriptor(final Path path, final Long size) { @@ -240,8 +243,7 @@ public class FSODescriptor implements VirtualFSODescriptorInterface { @Override public EntityID getLinkTarget() { - // TODO Auto-generated method stub - return null; + return linkTarget; } @Override @@ -258,4 +260,27 @@ public class FSODescriptor implements VirtualFSODescriptorInterface { public void setKey(String key) { this.key = key; } + + @Override + public Path getLinkTargetPath() { + return linkTargetPath; + } + + public void setLinkTarget(EntityID linkTarget) { + this.linkTarget = linkTarget; + } + + @Override + public void setLinkTargetPath(Path linkTargetPath) { + this.linkTargetPath = linkTargetPath; + } + + public static FSODescriptor createLink( + String fileStorageId, final Path path, final EntityID target) { + FSODescriptor result = new FSODescriptor(path); + result.fileStorageId = fileStorageId; + result.linkTarget = target; + result.type = ObjectType.LINK; + return result; + } } diff --git a/src/main/java/org/caosdb/server/filesystem/LocalFileStorage.java b/src/main/java/org/caosdb/server/filesystem/LocalFileStorage.java index 54fb698029048939851aa89719c7d6a8f2f2a10c..40836edbf5fd8ac9cd310a28385f3300801f1196 100644 --- a/src/main/java/org/caosdb/server/filesystem/LocalFileStorage.java +++ b/src/main/java/org/caosdb/server/filesystem/LocalFileStorage.java @@ -317,6 +317,30 @@ public abstract class LocalFileStorage implements FileStorageInterface { @Override public void cleanUp() {} }; + } else if (target.getObjectType() == ObjectType.LINK) { + final String newTargetPath = target.getLinkTargetPath().toString(); + final File newLink = targetPath.toFile(); + createSymlink(targetPath.toFile(), getRoot().resolve(newTargetPath).toFile()); + return new Undoable() { + + @Override + public void undo() { + // remove newly created directories + if (newLink != null) { + try { + FileUtils.forceDelete(newLink); + } catch (final Exception e) { + logger.error( + "Undo was not successfull. Could not delete link " + newLink.getAbsolutePath(), + e); + } + } + } + + @Override + public void cleanUp() {} + }; + } else { return rename(file.getFile(), targetPath.toFile()); } diff --git a/src/main/java/org/caosdb/server/filesystem/VirtualFSODescriptorInterface.java b/src/main/java/org/caosdb/server/filesystem/VirtualFSODescriptorInterface.java index fa5cf556311ab41d6cd60527dfbfbf53d0c3b9fb..f76c997ae1ee1396f99b5815000177851071548c 100644 --- a/src/main/java/org/caosdb/server/filesystem/VirtualFSODescriptorInterface.java +++ b/src/main/java/org/caosdb/server/filesystem/VirtualFSODescriptorInterface.java @@ -122,4 +122,8 @@ public interface VirtualFSODescriptorInterface extends FSODescriptorInterface { public abstract List<? extends VirtualFSODescriptorInterface> listChildren(); public abstract void setKey(String key); + + public abstract Path getLinkTargetPath(); + + public abstract void setLinkTargetPath(Path target); } diff --git a/src/main/java/org/caosdb/server/jobs/core/ListDirectory.java b/src/main/java/org/caosdb/server/jobs/core/ListDirectory.java new file mode 100644 index 0000000000000000000000000000000000000000..cd4bdd12c06b380a71fde753023aba62d2d9d3a2 --- /dev/null +++ b/src/main/java/org/caosdb/server/jobs/core/ListDirectory.java @@ -0,0 +1,33 @@ +package org.caosdb.server.jobs.core; + +import java.util.List; +import org.caosdb.server.entity.EntityInterface; +import org.caosdb.server.filesystem.FileSystem.ObjectType; +import org.caosdb.server.filesystem.VirtualFSODescriptorInterface; +import org.caosdb.server.jobs.EntityFlagJob; +import org.caosdb.server.jobs.JobAnnotation; +import org.caosdb.server.jobs.TransactionStage; + +@JobAnnotation( + defaultValue = "false", + loadOnDefault = false, + flag = "listDirectory", + values = {"true", "false"}, + stage = TransactionStage.POST_TRANSACTION) +public class ListDirectory extends EntityFlagJob { + + @Override + protected void job(String value) { + if ("true".equals(value) + && getEntity().hasFSODescriptor() + && getEntity().getFSODescriptor().getObjectType() == ObjectType.DIRECTORY) { + getEntity().getFSODescriptor().setChildren(listChildren(getEntity())); + } + } + + private List<VirtualFSODescriptorInterface> listChildren(EntityInterface entity) { + org.caosdb.server.database.backend.transaction.ListDirectory t = + new org.caosdb.server.database.backend.transaction.ListDirectory(entity.getId()); + return t.getChildren(); + } +} diff --git a/src/main/java/org/caosdb/server/jobs/core/LoadContainerFlagJobs.java b/src/main/java/org/caosdb/server/jobs/core/LoadContainerFlagJobs.java index a07862c0a8ced52a8caa1af2e845497eb64badd7..201a725fa17f99f187130b7ae7f8290499902cf3 100644 --- a/src/main/java/org/caosdb/server/jobs/core/LoadContainerFlagJobs.java +++ b/src/main/java/org/caosdb/server/jobs/core/LoadContainerFlagJobs.java @@ -23,7 +23,9 @@ package org.caosdb.server.jobs.core; import java.util.Map.Entry; +import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.jobs.ContainerJob; +import org.caosdb.server.jobs.EntityFlagJob; import org.caosdb.server.jobs.FlagJob; import org.caosdb.server.jobs.Job; import org.caosdb.server.jobs.JobAnnotation; @@ -42,6 +44,10 @@ public class LoadContainerFlagJobs extends ContainerJob { ((FlagJob) j).setValue(flag.getValue()); } getTransaction().getSchedule().add(j); + } else if (j != null && j instanceof EntityFlagJob) { + for (EntityInterface e : getContainer()) { + e.setFlag(flag.getKey(), flag.getValue()); + } } } } diff --git a/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java index 44ebfa22d08c975031f5bf5bfca325d6b706af24..bf5ccce8de2cc6d2d50fe563591c69cca91293c8 100644 --- a/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java +++ b/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java @@ -34,6 +34,7 @@ import java.sql.SQLException; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; import java.util.NoSuchElementException; import java.util.logging.Level; import org.apache.commons.fileupload.FileUploadException; @@ -71,7 +72,7 @@ import org.restlet.util.Series; */ public abstract class AbstractCaosDBServerResource extends ServerResource { - private final HashMap<String, String> flags = new HashMap<String, String>(); + private final Map<String, String> flags = new HashMap<String, String>(); private Long timestamp = null; private static final XMLParser xmlparser = new XMLParser(); protected String sRID = null; // Server side request ID @@ -415,7 +416,7 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { return this.requestedItems; } - public HashMap<String, String> getFlags() { + public Map<String, String> getFlags() { return this.flags; } diff --git a/src/main/java/org/caosdb/server/resource/FileSystemResource.java b/src/main/java/org/caosdb/server/resource/FileSystemResource.java index 49a072f0035c8c3eaf9a5d85279b962687154767..407d6aac0ff86c3c38030dd7ceb485d314e0c5cb 100644 --- a/src/main/java/org/caosdb/server/resource/FileSystemResource.java +++ b/src/main/java/org/caosdb/server/resource/FileSystemResource.java @@ -25,18 +25,23 @@ package org.caosdb.server.resource; import static java.net.URLDecoder.decode; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Map; import org.caosdb.server.database.backend.implementation.MySQL.ConnectionException; import org.caosdb.server.database.exceptions.EntityDoesNotExistException; import org.caosdb.server.database.misc.TransactionBenchmark; +import org.caosdb.server.entity.EntityID; import org.caosdb.server.entity.EntityInterface; import org.caosdb.server.entity.Message; import org.caosdb.server.entity.Message.MessageType; +import org.caosdb.server.entity.container.RetrieveContainer; import org.caosdb.server.filesystem.FileSystem; import org.caosdb.server.filesystem.FileSystem.ObjectType; import org.caosdb.server.filesystem.Path; import org.caosdb.server.filesystem.RealFSODescriptorInterface; import org.caosdb.server.filesystem.VirtualFSODescriptorInterface; import org.caosdb.server.permissions.EntityPermission; +import org.caosdb.server.transaction.Retrieve; import org.caosdb.server.transaction.RetrieveSparseEntityByPath; import org.caosdb.server.utils.ServerMessages; import org.jdom2.Document; @@ -72,24 +77,21 @@ public class FileSystemResource extends AbstractCaosDBServerResource { protected final Representation httpGetInChildClass() throws Exception { try { final long t1 = System.currentTimeMillis(); - final Path path = - new Path( - decode( - getRequest().getAttributes().containsKey("path") - ? (String) getRequest().getAttributes().get("path") - : "", - "UTF-8")); + final Path path = getPath(); final Element rootElem = generateRootElement(); final Document doc = new Document(rootElem); EntityInterface entity = null; VirtualFSODescriptorInterface file = null; - entity = getEntity(path); + entity = getEntityByPath(path); + if (entity.getFSODescriptor().getObjectType() == ObjectType.LINK) { + entity = getEntityById(entity.getFSODescriptor().getLinkTarget()); + } file = entity.getFSODescriptor(); if (file.getObjectType() == ObjectType.DIRECTORY) { - String referenceString = getReference().toString(); + String referenceString = getReferenceString(file); if (!referenceString.endsWith(Path.DEFAULT_PATH_SEPARATOR)) { referenceString = referenceString + Path.DEFAULT_PATH_SEPARATOR; } @@ -108,9 +110,10 @@ public class FileSystemResource extends AbstractCaosDBServerResource { "url", referenceString + child.getName() + Path.DEFAULT_PATH_SEPARATOR); break; case LINK: - // TODO - throw new UnsupportedOperationException( - "Unknown FileSystem.ObjectType: " + child.getObjectType().toString()); + celem = new Element("link"); + celem.setAttribute("name", child.getName()); + celem.setAttribute("url", referenceString + child.getName()); + break; case FILE: celem = new Element("file"); celem.setAttribute("name", child.getName()); @@ -158,6 +161,20 @@ public class FileSystemResource extends AbstractCaosDBServerResource { } } + private Path getPath() throws UnsupportedEncodingException { + return new Path( + decode( + getRequest().getAttributes().containsKey("path") + ? (String) getRequest().getAttributes().get("path") + : "", + "UTF-8")); + } + + private String getReferenceString(VirtualFSODescriptorInterface file) + throws UnsupportedEncodingException { + return getReference().toString().replaceFirst(getPath().toString(), file.getPath().toString()); + } + private Element toElement(final VirtualFSODescriptorInterface file) { // TODO return new Element("FileDescriptor"); @@ -167,9 +184,17 @@ public class FileSystemResource extends AbstractCaosDBServerResource { return TransactionBenchmark.getRootInstance().getBenchmark(getClass()); } - protected String getEntityID(final Path path) throws Exception { - final EntityInterface fileEnt = getEntity(path); - return fileEnt.getId().toString(); + private EntityInterface getEntityById(EntityID id) throws Exception { + final long t1 = System.currentTimeMillis(); + Map<String, String> flags = getFlags(); + flags.put("listDirectory", "true"); + RetrieveContainer c = new RetrieveContainer(getUser(), getTimestamp(), getSRID(), flags); + c.add(id); + Retrieve t = new Retrieve(c); + t.execute(); + final long t2 = System.currentTimeMillis(); + getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".getEntityById", t2 - t1); + return t.getContainer().get(0); } /** @@ -179,12 +204,12 @@ public class FileSystemResource extends AbstractCaosDBServerResource { * @return * @throws Exception */ - private EntityInterface getEntity(final Path path) throws Exception { + private EntityInterface getEntityByPath(final Path path) throws Exception { final long t1 = System.currentTimeMillis(); final RetrieveSparseEntityByPath t = new RetrieveSparseEntityByPath(path); t.execute(); final long t2 = System.currentTimeMillis(); - getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".getEntity", t2 - t1); + getBenchmark().addMeasurement(this.getClass().getSimpleName() + ".getEntityByPath", t2 - t1); return t.getEntity(); }