Search in sources :

Example 1 with FileSystemChangeSummary

use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.

the class AuditChangeFinderTestSuite method testFindChanges.

@Test
public void testFindChanges() throws Exception {
    List<FileSystemItemChange> changes;
    DocumentModel doc1;
    DocumentModel doc2;
    DocumentModel doc3;
    DocumentModel docToCopy;
    DocumentModel copiedDoc;
    DocumentModel docToVersion;
    commitAndWaitForAsyncCompletion();
    try {
        // No sync roots
        changes = getChanges();
        assertNotNull(changes);
        assertTrue(changes.isEmpty());
        log.trace("Sync roots for Administrator");
        nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder1, session);
        nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        // Get changes for Administrator
        changes = getChanges();
        // Root registration events
        assertEquals(2, changes.size());
        log.trace("Create 3 documents, only 2 in sync roots");
        doc1 = session.createDocumentModel("/folder1", "doc1", "File");
        doc1.setPropertyValue("file:content", new StringBlob("The content of file 1."));
        doc1 = session.createDocument(doc1);
        doc2 = session.createDocumentModel("/folder2", "doc2", "File");
        doc2.setPropertyValue("file:content", new StringBlob("The content of file 2."));
        doc2 = session.createDocument(doc2);
        doc3 = session.createDocumentModel("/folder3", "doc3", "File");
        doc3.setPropertyValue("file:content", new StringBlob("The content of file 3."));
        doc3 = session.createDocument(doc3);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(2, changes.size());
        Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
        expectedChanges.add(new SimpleFileSystemItemChange(doc2.getId(), "documentCreated", "test"));
        expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentCreated", "test"));
        assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
        // No changes since last successful sync
        changes = getChanges();
        assertTrue(changes.isEmpty());
        log.trace("Update both synchronized documents and unsynchronize a root");
        doc1.setPropertyValue("file:content", new StringBlob("The content of file 1, updated."));
        session.saveDocument(doc1);
        doc2.setPropertyValue("file:content", new StringBlob("The content of file 2, updated."));
        session.saveDocument(doc2);
        nuxeoDriveManager.unregisterSynchronizationRoot(session.getPrincipal(), folder2, session);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(2, changes.size());
        // The root unregistration is mapped to a fake deletion from the
        // client's point of view
        Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
        expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "deleted", "test"));
        expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentModified", "test"));
        assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
        log.trace("Delete a document with a lifecycle transition (trash)");
        session.followTransition(doc1.getRef(), "delete");
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(1, changes.size());
        assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test", "test#" + doc1.getId()), toSimpleFileSystemItemChange(changes.get(0)));
        log.trace("Restore a deleted document and move a document in a newly synchronized root");
        session.followTransition(doc1.getRef(), "undelete");
        session.move(doc3.getRef(), folder2.getRef(), null);
        nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(3, changes.size());
        Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
        expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "rootRegistered", "test", "defaultSyncRootFolderItemFactory#test#" + folder2.getId()));
        expectedChanges.add(new SimpleFileSystemItemChange(doc3.getId(), "documentMoved", "test"));
        expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "lifecycle_transition_event", "test"));
        assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
        log.trace("Physical deletion without triggering the delete transition first");
        session.removeDocument(doc3.getRef());
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(1, changes.size());
        assertEquals(new SimpleFileSystemItemChange(doc3.getId(), "deleted", "test", "test#" + doc3.getId()), toSimpleFileSystemItemChange(changes.get(0)));
        log.trace("Create a doc and copy it from a sync root to another one");
        docToCopy = session.createDocumentModel("/folder1", "docToCopy", "File");
        docToCopy.setPropertyValue("file:content", new StringBlob("The content of file to copy."));
        docToCopy = session.createDocument(docToCopy);
        copiedDoc = session.copy(docToCopy.getRef(), folder2.getRef(), null);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(2, changes.size());
        Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
        expectedChanges.add(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentCreatedByCopy", "test", "defaultFileSystemItemFactory#test#" + copiedDoc.getId(), "docToCopy"));
        expectedChanges.add(new SimpleFileSystemItemChange(docToCopy.getId(), "documentCreated", "test", "defaultFileSystemItemFactory#test#" + docToCopy.getId(), "docToCopy"));
        assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
        log.trace("Remove file from a document, mapped to a fake deletion from the client's point of view");
        doc1.setPropertyValue("file:content", null);
        session.saveDocument(doc1);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(1, changes.size());
        assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
        log.trace("Move a doc from a sync root to another sync root");
        session.move(copiedDoc.getRef(), folder1.getRef(), null);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(1, changes.size());
        assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentMoved", "test"), toSimpleFileSystemItemChange(changes.get(0)));
        log.trace("Move a doc from a sync root to a non synchronized folder");
        session.move(copiedDoc.getRef(), folder3.getRef(), null);
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        assertEquals(1, changes.size());
        assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
        log.trace("Create a doc, create a version of it, update doc and restore the version");
        docToVersion = session.createDocumentModel("/folder1", "docToVersion", "File");
        docToVersion.setPropertyValue("file:content", new StringBlob("The content of file to version."));
        docToVersion = session.createDocument(docToVersion);
        docToVersion.putContextData(VersioningService.VERSIONING_OPTION, VersioningOption.MAJOR);
        session.saveDocument(docToVersion);
        docToVersion.setPropertyValue("file:content", new StringBlob("Updated content of the versioned file."));
        session.saveDocument(docToVersion);
        List<DocumentModel> versions = session.getVersions(docToVersion.getRef());
        assertEquals(1, versions.size());
        DocumentModel version = versions.get(0);
        session.restoreToVersion(docToVersion.getRef(), version.getRef());
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    try {
        changes = getChanges();
        // Expecting 4 (among which 3 distinct) changes:
        // - documentRestored for docToVersion
        // - documentModified for docToVersion (2 occurrences)
        // - documentCreated for docToVersion
        assertEquals(4, changes.size());
        Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
        expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentRestored"));
        expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentModified"));
        expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentCreated"));
        assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
        log.trace("Too many changes");
        session.followTransition(doc1.getRef(), "delete");
        session.followTransition(doc2.getRef(), "delete");
    } finally {
        commitAndWaitForAsyncCompletion();
    }
    Framework.getProperties().put("org.nuxeo.drive.document.change.limit", "1");
    FileSystemChangeSummary changeSummary = getChangeSummary(session.getPrincipal());
    assertEquals(true, changeSummary.getHasTooManyChanges());
}
Also used : FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary) StringBlob(org.nuxeo.ecm.core.api.impl.blob.StringBlob) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 2 with FileSystemChangeSummary

use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.

the class TestGetChangeSummary method getChangeSummary.

/**
 * Gets the changes summary for the user bound to the {@link #session} using the {@link NuxeoDriveGetChangeSummary}
 * automation operation and updates the {@link #lastSyncDate} date.
 */
protected FileSystemChangeSummary getChangeSummary() throws Exception {
    // Wait 1 second as the mock change finder relies on steps of 1 second
    Thread.sleep(1000);
    Blob changeSummaryJSON = (Blob) clientSession.newRequest(NuxeoDriveGetChangeSummary.ID).set("lastSyncDate", lastSyncDate).set("lastSyncActiveRootDefinitions", lastSyncActiveRoots).execute();
    assertNotNull(changeSummaryJSON);
    FileSystemChangeSummary changeSummary = mapper.readValue(changeSummaryJSON.getStream(), FileSystemChangeSummaryImpl.class);
    assertNotNull(changeSummary);
    lastSyncDate = changeSummary.getSyncDate();
    lastSyncActiveRoots = changeSummary.getActiveSynchronizationRootDefinitions();
    return changeSummary;
}
Also used : StringBlob(org.nuxeo.ecm.core.api.impl.blob.StringBlob) Blob(org.nuxeo.ecm.automation.client.model.Blob) FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary)

Example 3 with FileSystemChangeSummary

use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.

the class TestGetChangeSummaryMultiRepo method testGetDocumentChangesSummary.

@Test
public void testGetDocumentChangesSummary() throws Exception {
    // Register 3 sync roots and create 3 documents: 2 in the 'test'
    // repository, 1 in the 'other' repository
    DocumentModel doc1;
    DocumentModel doc2;
    DocumentModel doc3;
    Principal administrator = session.getPrincipal();
    nuxeoDriveManager.registerSynchronizationRoot(administrator, folder1, session);
    nuxeoDriveManager.registerSynchronizationRoot(administrator, folder2, session);
    nuxeoDriveManager.registerSynchronizationRoot(administrator, folder3, otherSession);
    doc1 = session.createDocumentModel("/folder1", "doc1", "File");
    doc1.setPropertyValue("file:content", new StringBlob("The content of file 1."));
    doc1 = session.createDocument(doc1);
    doc2 = session.createDocumentModel("/folder2", "doc2", "File");
    doc2.setPropertyValue("file:content", new StringBlob("The content of file 2."));
    doc2 = session.createDocument(doc2);
    doc3 = otherSession.createDocumentModel("/folder3", "doc3", "File");
    doc3.setPropertyValue("file:content", new StringBlob("The content of file 3."));
    doc3 = otherSession.createDocument(doc3);
    TransactionHelper.commitOrRollbackTransaction();
    TransactionHelper.startTransaction();
    // Look in all repositories => should find 3 changes
    FileSystemChangeSummary changeSummary = getChangeSummary();
    List<FileSystemItemChange> docChanges = changeSummary.getFileSystemChanges();
    assertEquals(3, docChanges.size());
    Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
    expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentChanged", "test"));
    expectedChanges.add(new SimpleFileSystemItemChange(doc2.getId(), "documentChanged", "test"));
    expectedChanges.add(new SimpleFileSystemItemChange(doc3.getId(), "documentChanged", "other"));
    Set<SimpleFileSystemItemChange> changes = new HashSet<>();
    docChanges.forEach(docChange -> {
        changes.add(new SimpleFileSystemItemChange(docChange.getDocUuid(), docChange.getEventId(), docChange.getRepositoryId()));
        assertNotNull(docChange.getFileSystemItem());
    });
    assertTrue(CollectionUtils.isEqualCollection(expectedChanges, changes));
    assertEquals(Boolean.FALSE, changeSummary.getHasTooManyChanges());
    // Update documents
    doc1.setPropertyValue("dc:description", "Added description to doc1.");
    doc2.setPropertyValue("dc:description", "Added description to doc1.");
    doc3.setPropertyValue("dc:description", "Added description to doc1.");
    session.saveDocument(doc1);
    session.saveDocument(doc2);
    otherSession.saveDocument(doc3);
    TransactionHelper.commitOrRollbackTransaction();
    TransactionHelper.startTransaction();
    changeSummary = getChangeSummary();
    docChanges = changeSummary.getFileSystemChanges();
    assertEquals(3, docChanges.size());
}
Also used : FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary) StringBlob(org.nuxeo.ecm.core.api.impl.blob.StringBlob) SimpleFileSystemItemChange(org.nuxeo.drive.fixtures.SimpleFileSystemItemChange) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) SimpleFileSystemItemChange(org.nuxeo.drive.fixtures.SimpleFileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel) Principal(java.security.Principal) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 4 with FileSystemChangeSummary

use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.

the class NuxeoDriveGetChangeSummary method run.

@OperationMethod
public Blob run() throws IOException {
    NuxeoDriveManager driveManager = Framework.getService(NuxeoDriveManager.class);
    Map<String, Set<IdRef>> lastActiveRootRefs = RootDefinitionsHelper.parseRootDefinitions(lastSyncActiveRootDefinitions);
    FileSystemChangeSummary docChangeSummary;
    if (lastSyncDate >= 0) {
        docChangeSummary = driveManager.getChangeSummary(ctx.getPrincipal(), lastActiveRootRefs, lastSyncDate);
    } else {
        docChangeSummary = driveManager.getChangeSummaryIntegerBounds(ctx.getPrincipal(), lastActiveRootRefs, lowerBound);
    }
    return Blobs.createJSONBlobFromValue(docChangeSummary);
}
Also used : Set(java.util.Set) FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary) NuxeoDriveManager(org.nuxeo.drive.service.NuxeoDriveManager) OperationMethod(org.nuxeo.ecm.automation.core.annotations.OperationMethod)

Example 5 with FileSystemChangeSummary

use of org.nuxeo.drive.service.FileSystemChangeSummary in project nuxeo-drive-server by nuxeo.

the class NuxeoDriveManagerImpl method getChangeSummary.

protected FileSystemChangeSummary getChangeSummary(Principal principal, Map<String, Set<IdRef>> lastActiveRootRefs, Map<String, SynchronizationRoots> roots, Map<String, Set<String>> collectionSyncRootMemberIds, long lowerBound, boolean integerBounds) {
    List<FileSystemItemChange> allChanges = new ArrayList<FileSystemItemChange>();
    // Compute the list of all repositories to consider for the aggregate summary
    Set<String> allRepositories = new TreeSet<String>();
    allRepositories.addAll(roots.keySet());
    allRepositories.addAll(lastActiveRootRefs.keySet());
    allRepositories.addAll(collectionSyncRootMemberIds.keySet());
    long syncDate;
    long upperBound;
    if (integerBounds) {
        upperBound = changeFinder.getUpperBound(allRepositories);
        // Truncate sync date to 0 milliseconds
        syncDate = System.currentTimeMillis();
        syncDate = syncDate - (syncDate % 1000);
    } else {
        upperBound = changeFinder.getCurrentDate();
        syncDate = upperBound;
    }
    Boolean hasTooManyChanges = Boolean.FALSE;
    int limit = Integer.parseInt(Framework.getProperty(DOCUMENT_CHANGE_LIMIT_PROPERTY, "1000"));
    if (!allRepositories.isEmpty() && lowerBound >= 0 && upperBound > lowerBound) {
        for (String repositoryName : allRepositories) {
            try (CloseableCoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) {
                // Get document changes
                Set<IdRef> lastRefs = lastActiveRootRefs.get(repositoryName);
                if (lastRefs == null) {
                    lastRefs = Collections.emptySet();
                }
                SynchronizationRoots activeRoots = roots.get(repositoryName);
                if (activeRoots == null) {
                    activeRoots = SynchronizationRoots.getEmptyRoots(repositoryName);
                }
                Set<String> repoCollectionSyncRootMemberIds = collectionSyncRootMemberIds.get(repositoryName);
                if (repoCollectionSyncRootMemberIds == null) {
                    repoCollectionSyncRootMemberIds = Collections.emptySet();
                }
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Start: getting FileSystemItem changes for repository %s / user %s between %s and %s with activeRoots = %s", repositoryName, principal.getName(), lowerBound, upperBound, activeRoots.getPaths()));
                }
                List<FileSystemItemChange> changes;
                if (integerBounds) {
                    changes = changeFinder.getFileSystemChangesIntegerBounds(session, lastRefs, activeRoots, repoCollectionSyncRootMemberIds, lowerBound, upperBound, limit);
                } else {
                    changes = changeFinder.getFileSystemChanges(session, lastRefs, activeRoots, lowerBound, upperBound, limit);
                }
                allChanges.addAll(changes);
            } catch (TooManyChangesException e) {
                hasTooManyChanges = Boolean.TRUE;
                allChanges.clear();
                break;
            }
        }
    }
    // Send back to the client the list of currently active roots to be able
    // to efficiently detect root unregistration events for the next
    // incremental change summary
    Map<String, Set<IdRef>> activeRootRefs = new HashMap<String, Set<IdRef>>();
    for (Map.Entry<String, SynchronizationRoots> rootsEntry : roots.entrySet()) {
        activeRootRefs.put(rootsEntry.getKey(), rootsEntry.getValue().getRefs());
    }
    FileSystemChangeSummary summary = new FileSystemChangeSummaryImpl(allChanges, activeRootRefs, syncDate, upperBound, hasTooManyChanges);
    if (log.isDebugEnabled()) {
        log.debug(String.format("End: getting %d FileSystemItem changes for user %s between %s and %s with activeRoots = %s -> %s", allChanges.size(), principal.getName(), lowerBound, upperBound, roots, summary));
    }
    return summary;
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary) ArrayList(java.util.ArrayList) CloseableCoreSession(org.nuxeo.ecm.core.api.CloseableCoreSession) SynchronizationRoots(org.nuxeo.drive.service.SynchronizationRoots) IdRef(org.nuxeo.ecm.core.api.IdRef) TreeSet(java.util.TreeSet) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) TooManyChangesException(org.nuxeo.drive.service.TooManyChangesException) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

FileSystemChangeSummary (org.nuxeo.drive.service.FileSystemChangeSummary)11 HashSet (java.util.HashSet)6 FileSystemItemChange (org.nuxeo.drive.service.FileSystemItemChange)6 StringBlob (org.nuxeo.ecm.core.api.impl.blob.StringBlob)6 Test (org.junit.Test)5 Principal (java.security.Principal)4 DocumentModel (org.nuxeo.ecm.core.api.DocumentModel)4 Set (java.util.Set)3 IdRef (org.nuxeo.ecm.core.api.IdRef)3 SimpleFileSystemItemChange (org.nuxeo.drive.fixtures.SimpleFileSystemItemChange)2 Blob (org.nuxeo.ecm.automation.client.model.Blob)2 NuxeoPrincipalImpl (org.nuxeo.ecm.platform.usermanager.NuxeoPrincipalImpl)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 TreeSet (java.util.TreeSet)1 NuxeoDriveManager (org.nuxeo.drive.service.NuxeoDriveManager)1 SynchronizationRoots (org.nuxeo.drive.service.SynchronizationRoots)1 TooManyChangesException (org.nuxeo.drive.service.TooManyChangesException)1