/** * Get the canonical path to the file's meta file. * * @param bcPath * @return String */ private VFSLeaf getCanonicalVersionXmlFile(VFSItem item, boolean create) { File f = getOriginFile(item); if (!f.exists()) { return null; } String relPath = getRelPath(item); if (relPath == null) { // cannot handle return null; } File fVersion = new File(getRootVersionsFile(), relPath + ".xml"); File fParentVersion = fVersion.getParentFile(); if (!fParentVersion.exists() && create) { fParentVersion.mkdirs(); } if (fVersion.exists()) { LocalFolderImpl localVersionContainer = new LocalFolderImpl(fParentVersion); return (VFSLeaf) localVersionContainer.resolve(fVersion.getName()); } else if (create) { LocalFolderImpl localVersionContainer = new LocalFolderImpl(fParentVersion); VersionsFileImpl versions = new VersionsFileImpl(); versions.setVersioned(isVersioned(item)); versions.setRevisionNr(getNextRevisionNr(versions)); VFSLeaf fVersions = localVersionContainer.createChildLeaf(fVersion.getName()); XStreamHelper.writeObject(mystream, fVersions, versions); return fVersions; } return null; }
private Versions readVersions(VFSLeaf leaf, VFSLeaf fVersions) { if (fVersions == null) { return new NotVersioned(); } try { VFSContainer fVersionContainer = fVersions.getParentContainer(); VersionsFileImpl versions = (VersionsFileImpl) XStreamHelper.readObject(mystream, fVersions); versions.setVersionFile(fVersions); versions.setCurrentVersion((Versionable) leaf); if (versions.getRevisionNr() == null || versions.getRevisionNr().length() == 0) { versions.setRevisionNr(getNextRevisionNr(versions)); } for (VFSRevision revision : versions.getRevisions()) { RevisionFileImpl revisionImpl = (RevisionFileImpl) revision; revisionImpl.setContainer(fVersionContainer); } return versions; } catch (Exception e) { log.warn("This file is not a versions XML file: " + fVersions, e); fVersions.delete(); VersionsFileImpl versions = new VersionsFileImpl(); versions.setCurrentVersion((Versionable) leaf); versions.setVersioned(isVersioned(leaf)); versions.setRevisionNr(getNextRevisionNr(versions)); log.warn("Deleted corrupt version XML file and created new version XML file: " + versions); // the old revisions can not be restored automatically. They are still on disk, you could // recover them // manually. This is not a perfect solution, but at least the user does not get an RS return versions; } }
/** @see org.olat.core.configuration.Initializable#init() */ public void init() { mystream = XStreamHelper.createXStreamInstance(); mystream.alias("versions", VersionsFileImpl.class); mystream.alias("revision", RevisionFileImpl.class); mystream.omitField(VersionsFileImpl.class, "currentVersion"); mystream.omitField(VersionsFileImpl.class, "versionFile"); mystream.omitField(RevisionFileImpl.class, "current"); mystream.omitField(RevisionFileImpl.class, "container"); mystream.omitField(RevisionFileImpl.class, "file"); }
private Versions isOrphan(VFSLeaf potentialOrphan) { try { if (potentialOrphan.exists()) { VersionsFileImpl versions = (VersionsFileImpl) XStreamHelper.readObject(mystream, potentialOrphan); return versions; } return null; } catch (Exception e) { return null; } }
@Override public boolean deleteRevisions(Versionable currentVersion, List<VFSRevision> versionsToDelete) { VFSLeaf currentFile = (VFSLeaf) currentVersion; Versions versions = readVersions(currentFile, true); List<VFSRevision> allVersions = versions.getRevisions(); Map<String, VFSLeaf> filenamesToDelete = new HashMap<String, VFSLeaf>(allVersions.size()); for (VFSRevision versionToDelete : versionsToDelete) { RevisionFileImpl versionImpl = (RevisionFileImpl) versionToDelete; for (Iterator<VFSRevision> allVersionIt = allVersions.iterator(); allVersionIt.hasNext(); ) { RevisionFileImpl allVersionImpl = (RevisionFileImpl) allVersionIt.next(); if (allVersionImpl.getFilename() != null && allVersionImpl.getFilename().equals(versionImpl.getFilename())) { allVersionIt.remove(); break; } } VFSLeaf fileToDelete = versionImpl.getFile(); if (fileToDelete != null) { filenamesToDelete.put(fileToDelete.getName(), fileToDelete); } } List<RevisionFileImpl> missingFiles = new ArrayList<>(); for (VFSRevision survivingVersion : allVersions) { RevisionFileImpl survivingVersionImpl = (RevisionFileImpl) survivingVersion; VFSLeaf revFile = survivingVersionImpl.getFile(); if (revFile == null) { missingFiles.add(survivingVersionImpl); // file is missing } else if (filenamesToDelete.containsKey(revFile.getName())) { filenamesToDelete.remove(revFile.getName()); } } if (missingFiles.size() > 0) { allVersions.removeAll(missingFiles); } for (VFSLeaf fileToDelete : filenamesToDelete.values()) { fileToDelete.deleteSilently(); } VFSLeaf versionFile = getCanonicalVersionXmlFile(currentFile, true); XStreamHelper.writeObject(mystream, versionFile, versions); if (currentVersion.getVersions() instanceof VersionsFileImpl) { ((VersionsFileImpl) currentVersion.getVersions()).update(versions); } return true; }
@Override public boolean restore(VFSContainer container, VFSRevision revision) { String filename = revision.getName(); VFSItem restoredItem = container.resolve(filename); if (restoredItem == null) { restoredItem = container.createChildLeaf(filename); } if (restoredItem instanceof VFSLeaf) { VFSLeaf restoredLeaf = (VFSLeaf) restoredItem; InputStream inStream = revision.getInputStream(); if (VFSManager.copyContent(inStream, restoredLeaf)) { VFSLeaf versionFile = getCanonicalVersionXmlFile(restoredLeaf, true); Versions versions = readVersions(restoredLeaf, versionFile); if (versions instanceof VersionsFileImpl) { versions.getRevisions().remove(revision); ((VersionsFileImpl) versions).setRevisionNr(getNextRevisionNr(versions)); } XStreamHelper.writeObject(mystream, versionFile, versions); return true; } } return false; }
@Override public boolean move(VFSLeaf currentFile, VFSLeaf targetFile, Identity author) { VFSLeaf fCurrentVersions = getCanonicalVersionXmlFile(currentFile, true); Versions currentVersions = readVersions(currentFile, fCurrentVersions); boolean brandNewVersionFile = false; VFSLeaf fTargetVersions = getCanonicalVersionXmlFile(targetFile, false); if (fTargetVersions == null) { brandNewVersionFile = true; fTargetVersions = getCanonicalVersionXmlFile(targetFile, true); } Versions targetVersions = readVersions(targetFile, fTargetVersions); if (!(currentVersions instanceof VersionsFileImpl) || !(targetVersions instanceof VersionsFileImpl)) { return false; } VersionsFileImpl targetVersionsImpl = (VersionsFileImpl) targetVersions; if (author != null) { targetVersionsImpl.setAuthor(author.getName()); } if (brandNewVersionFile) { targetVersionsImpl.setCreator(currentVersions.getCreator()); targetVersionsImpl.setComment(currentVersions.getComment()); } boolean allOk = true; for (VFSRevision revision : currentVersions.getRevisions()) { allOk &= copyRevision(revision, fTargetVersions, targetVersionsImpl); } targetVersionsImpl.setRevisionNr(getNextRevisionNr(targetVersionsImpl)); XStreamHelper.writeObject(mystream, fTargetVersions, targetVersionsImpl); return allOk; }
/** * @see * org.olat.core.util.vfs.version.VersionsManager#addToRevisions(org.olat.core.util.vfs.version.Versionable, * org.olat.core.id.Identity, java.lang.String) */ @Override public boolean addToRevisions(Versionable currentVersion, Identity identity, String comment) { int maxNumOfVersions = versioningConfigurator.getMaxNumOfVersionsAllowed(); if (maxNumOfVersions == 0) { return true; // deactivated, return all ok } VFSLeaf currentFile = (VFSLeaf) currentVersion; VFSLeaf versionFile = getCanonicalVersionXmlFile(currentFile, true); if (versionFile == null) { return false; // cannot do something with the current file } VFSContainer versionContainer = versionFile.getParentContainer(); String name = currentFile.getName(); // read from the Versions v = readVersions(currentFile, versionFile); if (!(v instanceof VersionsFileImpl)) { log.error("Wrong implementation of Versions: " + v); return false; } VersionsFileImpl versions = (VersionsFileImpl) v; boolean sameFile = isSameFile(currentFile, versions); String uuid = sameFile ? getLastRevisionFilename(versions) : UUID.randomUUID().toString() + "_" + name; String versionNr = getNextRevisionNr(versions); String currentAuthor = versions.getAuthor(); long lastModifiedDate = 0; if (currentFile instanceof MetaTagged) { MetaInfo metaInfo = ((MetaTagged) currentFile).getMetaInfo(); if (metaInfo != null) { metaInfo.clearThumbnails(); if (currentAuthor == null) { currentAuthor = metaInfo.getAuthor(); } lastModifiedDate = metaInfo.getLastModified(); } } if (lastModifiedDate <= 0) { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); lastModifiedDate = cal.getTimeInMillis(); } RevisionFileImpl newRevision = new RevisionFileImpl(); newRevision.setUuid(UUID.randomUUID().toString()); newRevision.setName(name); newRevision.setFilename(uuid); newRevision.setRevisionNr(versionNr); newRevision.setComment(versions.getComment()); newRevision.setAuthor(currentAuthor); newRevision.setLastModified(lastModifiedDate); if (versions.getRevisions().isEmpty() && currentVersion instanceof MetaTagged) { MetaTagged metaTagged = (MetaTagged) currentVersion; versions.setCreator(metaTagged.getMetaInfo().getAuthor()); } if (sameFile || VFSManager.copyContent(currentFile, versionContainer.createChildLeaf(uuid))) { if (identity != null) { versions.setAuthor(identity.getName()); } if (maxNumOfVersions >= 0 && versions.getRevisions().size() >= maxNumOfVersions) { List<VFSRevision> revisions = versions.getRevisions(); int numOfVersionsToDelete = Math.min(revisions.size(), (revisions.size() - maxNumOfVersions) + 1); if (numOfVersionsToDelete > 0) { List<VFSRevision> versionsToDelete = revisions.subList(0, numOfVersionsToDelete); deleteRevisions(currentVersion, versionsToDelete); versions = (VersionsFileImpl) currentVersion.getVersions(); } } versions.setComment(comment); versions.getRevisions().add(newRevision); versions.setRevisionNr(getNextRevisionNr(versions)); XStreamHelper.writeObject(mystream, versionFile, versions); if (currentVersion.getVersions() instanceof VersionsFileImpl) { ((VersionsFileImpl) currentVersion.getVersions()).update(versions); } return true; } else { log.error("Cannot create a version of this file: " + currentVersion); } return false; }