use of org.nuxeo.drive.service.SynchronizationRoots in project nuxeo-drive-server by nuxeo.
the class DefaultTopLevelFolderItem method getChildren.
/*--------------------- FolderItem -----------------*/
@Override
public List<FileSystemItem> getChildren() {
List<FileSystemItem> children = new ArrayList<FileSystemItem>();
Map<String, SynchronizationRoots> syncRootsByRepo = Framework.getService(NuxeoDriveManager.class).getSynchronizationRoots(principal);
for (String repositoryName : syncRootsByRepo.keySet()) {
try (CloseableCoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) {
Set<IdRef> syncRootRefs = syncRootsByRepo.get(repositoryName).getRefs();
Iterator<IdRef> syncRootRefsIt = syncRootRefs.iterator();
while (syncRootRefsIt.hasNext()) {
IdRef idRef = syncRootRefsIt.next();
// See https://jira.nuxeo.com/browse/NXP-11146
if (!session.hasPermission(idRef, SecurityConstants.READ)) {
if (log.isDebugEnabled()) {
log.debug(String.format("User %s has no READ access on synchronization root %s, not including it in children.", session.getPrincipal().getName(), idRef));
}
continue;
}
DocumentModel doc = session.getDocument(idRef);
// NXP-19442: Avoid useless and costly call to DocumentModel#getLockInfo
FileSystemItem child = getFileSystemItemAdapterService().getFileSystemItem(doc, this, false, false, false);
if (child == null) {
if (log.isDebugEnabled()) {
log.debug(String.format("Synchronization root %s cannot be adapted as a FileSystemItem, not including it in children.", idRef));
}
continue;
}
if (log.isDebugEnabled()) {
log.debug(String.format("Including synchronization root %s in children.", idRef));
}
children.add(child);
}
}
}
Collections.sort(children);
return children;
}
use of org.nuxeo.drive.service.SynchronizationRoots 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;
}
use of org.nuxeo.drive.service.SynchronizationRoots in project nuxeo-drive-server by nuxeo.
the class NuxeoDriveManagerImpl method isSynchronizationRoot.
@Override
public boolean isSynchronizationRoot(Principal principal, DocumentModel doc) {
String repoName = doc.getRepositoryName();
SynchronizationRoots syncRoots = getSynchronizationRoots(principal).get(repoName);
return syncRoots.getRefs().contains(doc.getRef());
}
use of org.nuxeo.drive.service.SynchronizationRoots in project nuxeo-drive-server by nuxeo.
the class NuxeoDriveManagerImpl method registerSynchronizationRoot.
@Override
public void registerSynchronizationRoot(Principal principal, final DocumentModel newRootContainer, CoreSession session) {
final String userName = principal.getName();
if (log.isDebugEnabled()) {
log.debug(String.format("Registering synchronization root %s for %s", newRootContainer, userName));
}
// If new root is child of a sync root, ignore registration, except for
// the 'Locally Edited' collection: it is under the personal workspace
// and we want to allow both the personal workspace and the 'Locally
// Edited' collection to be registered as sync roots
Map<String, SynchronizationRoots> syncRoots = getSynchronizationRoots(principal);
SynchronizationRoots synchronizationRoots = syncRoots.get(session.getRepositoryName());
if (!NuxeoDriveManager.LOCALLY_EDITED_COLLECTION_NAME.equals(newRootContainer.getName())) {
for (String syncRootPath : synchronizationRoots.getPaths()) {
String syncRootPrefixedPath = syncRootPath + "/";
if (newRootContainer.getPathAsString().startsWith(syncRootPrefixedPath)) {
// the only exception is when the right inheritance is
// blocked
// in the hierarchy
boolean rightInheritanceBlockedInTheHierarchy = false;
// should get only parents up to the sync root
Path parentPath = newRootContainer.getPath().removeLastSegments(1);
while (!"/".equals(parentPath.toString())) {
String parentPathAsString = parentPath.toString() + "/";
if (!parentPathAsString.startsWith(syncRootPrefixedPath)) {
break;
}
PathRef parentRef = new PathRef(parentPathAsString);
if (!session.hasPermission(principal, parentRef, SecurityConstants.READ)) {
rightInheritanceBlockedInTheHierarchy = true;
break;
}
parentPath = parentPath.removeLastSegments(1);
}
if (!rightInheritanceBlockedInTheHierarchy) {
return;
}
}
}
}
checkCanUpdateSynchronizationRoot(newRootContainer, session);
// Unregister any sub-folder of the new root, except for the 'Locally
// Edited' collection
String newRootPrefixedPath = newRootContainer.getPathAsString() + "/";
for (String existingRootPath : synchronizationRoots.getPaths()) {
if (!existingRootPath.endsWith(NuxeoDriveManager.LOCALLY_EDITED_COLLECTION_NAME)) {
if (existingRootPath.startsWith(newRootPrefixedPath)) {
// Unregister the nested root sub-folder first
PathRef ref = new PathRef(existingRootPath);
if (session.exists(ref)) {
DocumentModel subFolder = session.getDocument(ref);
unregisterSynchronizationRoot(principal, subFolder, session);
}
}
}
}
UnrestrictedSessionRunner runner = new UnrestrictedSessionRunner(session) {
@Override
public void run() {
if (!newRootContainer.hasFacet(NUXEO_DRIVE_FACET)) {
newRootContainer.addFacet(NUXEO_DRIVE_FACET);
}
fireEvent(newRootContainer, session, NuxeoDriveEvents.ABOUT_TO_REGISTER_ROOT, userName);
@SuppressWarnings("unchecked") List<Map<String, Object>> subscriptions = (List<Map<String, Object>>) newRootContainer.getPropertyValue(DRIVE_SUBSCRIPTIONS_PROPERTY);
boolean updated = false;
for (Map<String, Object> subscription : subscriptions) {
if (userName.equals(subscription.get("username"))) {
subscription.put("enabled", Boolean.TRUE);
subscription.put("lastChangeDate", Calendar.getInstance(UTC));
updated = true;
break;
}
}
if (!updated) {
Map<String, Object> subscription = new HashMap<String, Object>();
subscription.put("username", userName);
subscription.put("enabled", Boolean.TRUE);
subscription.put("lastChangeDate", Calendar.getInstance(UTC));
subscriptions.add(subscription);
}
newRootContainer.setPropertyValue(DRIVE_SUBSCRIPTIONS_PROPERTY, (Serializable) subscriptions);
newRootContainer.putContextData(NXAuditEventsService.DISABLE_AUDIT_LOGGER, true);
newRootContainer.putContextData(NotificationConstants.DISABLE_NOTIFICATION_SERVICE, true);
newRootContainer.putContextData(CoreSession.SOURCE, "drive");
DocumentModel savedNewRootContainer = session.saveDocument(newRootContainer);
newRootContainer.putContextData(NXAuditEventsService.DISABLE_AUDIT_LOGGER, false);
newRootContainer.putContextData(NotificationConstants.DISABLE_NOTIFICATION_SERVICE, false);
fireEvent(savedNewRootContainer, session, NuxeoDriveEvents.ROOT_REGISTERED, userName);
session.save();
}
};
runner.runUnrestricted();
invalidateSynchronizationRootsCache(userName);
invalidateCollectionSyncRootMemberCache(userName);
}
use of org.nuxeo.drive.service.SynchronizationRoots in project nuxeo-drive-server by nuxeo.
the class NuxeoDriveManagerImpl method queryAndFetchSynchronizationRoots.
protected Map<String, SynchronizationRoots> queryAndFetchSynchronizationRoots(CoreSession session, String query) {
Map<String, SynchronizationRoots> syncRoots = new HashMap<String, SynchronizationRoots>();
Set<IdRef> references = new LinkedHashSet<IdRef>();
Set<String> paths = new LinkedHashSet<String>();
IterableQueryResult results = session.queryAndFetch(query, NXQL.NXQL);
try {
for (Map<String, Serializable> result : results) {
IdRef docRef = new IdRef(result.get("ecm:uuid").toString());
try {
DocumentModel doc = session.getDocument(docRef);
references.add(docRef);
paths.add(doc.getPathAsString());
} catch (DocumentNotFoundException e) {
log.warn(String.format("Document %s not found, not adding it to the list of synchronization roots for user %s.", docRef, session.getPrincipal().getName()));
} catch (DocumentSecurityException e) {
log.warn(String.format("User %s cannot access document %s, not adding it to the list of synchronization roots.", session.getPrincipal().getName(), docRef));
}
}
} finally {
results.close();
}
SynchronizationRoots repoSyncRoots = new SynchronizationRoots(session.getRepositoryName(), paths, references);
syncRoots.put(session.getRepositoryName(), repoSyncRoots);
return syncRoots;
}
Aggregations