use of org.exist.collections.Collection in project exist by eXist-db.
the class EmbeddedOutputStream method uploadToDb.
private static void uploadToDb(final BrokerPool pool, final XmldbURL url, final Path tempFile) throws IOException {
try (final DBBroker broker = pool.getBroker()) {
final XmldbURI collectionUri = XmldbURI.create(url.getCollection());
final XmldbURI documentUri = XmldbURI.create(url.getDocumentName());
try (final Collection collection = broker.openCollection(collectionUri, Lock.LockMode.WRITE_LOCK)) {
if (collection == null) {
throw new IOException("Resource " + collectionUri.toString() + " is not a collection.");
}
if (collection.hasChildCollection(broker, documentUri)) {
throw new IOException("Resource " + documentUri.toString() + " is a collection.");
}
final MimeType mime = MimeTable.getInstance().getContentTypeFor(documentUri);
final TransactionManager transact = pool.getTransactionManager();
try (final Txn txn = transact.beginTransaction()) {
broker.storeDocument(txn, documentUri, new FileInputSource(tempFile), mime, collection);
txn.commit();
}
}
} catch (final EXistException | PermissionDeniedException | LockException | SAXException e) {
LOG.error(e);
throw new IOException(e.getMessage(), e);
} finally {
if (LOG.isDebugEnabled()) {
LOG.debug("End document upload");
}
}
}
use of org.exist.collections.Collection in project exist by eXist-db.
the class NativeBroker method reindexCollection.
@Override
public void reindexCollection(final Txn transaction, final XmldbURI collectionUri) throws PermissionDeniedException, IOException, LockException {
if (isReadOnly()) {
throw new IOException(DATABASE_IS_READ_ONLY);
}
final XmldbURI fqUri = prepend(collectionUri.toCollectionPathURI());
final long start = System.currentTimeMillis();
try (final Collection collection = openCollection(fqUri, LockMode.READ_LOCK)) {
if (collection == null) {
LOG.warn("Collection {} not found!", fqUri);
return;
}
LOG.info("Start indexing collection {}", collection.getURI().toString());
pool.getProcessMonitor().startJob(ProcessMonitor.ACTION_REINDEX_COLLECTION, collection.getURI());
reindexCollection(transaction, collection, IndexMode.STORE);
} catch (final PermissionDeniedException | IOException e) {
LOG.error("An error occurred during reindex: {}", e.getMessage(), e);
} finally {
pool.getProcessMonitor().endJob();
LOG.info("Finished indexing collection {} in {} ms.", fqUri, System.currentTimeMillis() - start);
}
}
use of org.exist.collections.Collection in project exist by eXist-db.
the class NativeBroker method lockDescendantDocuments.
/**
* Acquires locks on all descendant Collections of a specific Collection
*
* Locks are acquired in a top-down, left-to-right order
*
* NOTE: It is assumed that the caller holds a lock on the
* `collection` of the same mode as those that we should acquire on the descendants
*
* @param collection The Collection whose descendant locks should be acquired
* @param lockFn A function for acquiring a lock
*
* @return A list of locks in the same order as collectionUris. Note that these should be released in reverse order
*/
private List<ManagedDocumentLock> lockDescendantDocuments(final Collection collection, final FunctionE<XmldbURI, ManagedDocumentLock, LockException> lockFn) throws LockException, PermissionDeniedException {
final List<ManagedDocumentLock> locks = new ArrayList<>();
try {
final Iterator<DocumentImpl> itDoc = collection.iteratorNoLock(this);
while (itDoc.hasNext()) {
final DocumentImpl doc = itDoc.next();
final ManagedDocumentLock docLock = lockFn.apply(doc.getURI());
locks.add(docLock);
}
final XmldbURI collectionUri = collection.getURI();
// NOTE: we should already have a lock on collection
final Iterator<XmldbURI> it = collection.collectionIteratorNoLock(this);
while (it.hasNext()) {
final XmldbURI childCollectionName = it.next();
final XmldbURI childCollectionUri = collectionUri.append(childCollectionName);
// NOTE: we don't need to lock the collection as we should already implicitly have a lock on the collection sub-tree
final Collection childCollection = getCollection(childCollectionUri);
final List<ManagedDocumentLock> descendantLocks = lockDescendantDocuments(childCollection, lockFn);
locks.addAll(descendantLocks);
}
} catch (final PermissionDeniedException | LockException e) {
// unlock in reverse order
try {
ManagedLocks.closeAll(locks);
} catch (final RuntimeException re) {
LOG.error(re);
}
throw e;
}
return locks;
}
use of org.exist.collections.Collection in project exist by eXist-db.
the class NativeBroker method copyResource.
@Override
public void copyResource(final Txn transaction, final DocumentImpl sourceDocument, final Collection targetCollection, final XmldbURI newDocName, final PreserveType preserve) throws PermissionDeniedException, LockException, IOException, TriggerException, EXistException {
assert (sourceDocument != null);
assert (targetCollection != null);
assert (newDocName != null);
if (isReadOnly()) {
throw new IOException(DATABASE_IS_READ_ONLY);
}
if (newDocName.numSegments() != 1) {
throw new IOException("newName name must be just a name i.e. an XmldbURI with one segment!");
}
final XmldbURI sourceDocumentUri = sourceDocument.getURI();
final XmldbURI targetCollectionUri = targetCollection.getURI();
final XmldbURI targetDocumentUri = targetCollectionUri.append(newDocName);
if (!sourceDocument.getPermissions().validate(getCurrentSubject(), Permission.READ)) {
throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' has insufficient privileges to copy the resource '" + sourceDocumentUri + "'.");
}
// we assume the caller holds a READ_LOCK (or better) on sourceDocument#getCollection()
final Collection sourceCollection = sourceDocument.getCollection();
if (!sourceCollection.getPermissions().validate(getCurrentSubject(), Permission.EXECUTE)) {
throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' has insufficient privileges to copy the resource '" + sourceDocumentUri + "'.");
}
if (!targetCollection.getPermissionsNoLock().validate(getCurrentSubject(), Permission.EXECUTE)) {
throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' does not have execute access on the destination collection '" + targetCollectionUri + "'.");
}
if (targetCollection.hasChildCollection(this, newDocName.lastSegment())) {
throw new EXistException("The collection '" + targetCollectionUri + "' already has a sub-collection named '" + newDocName.lastSegment() + "', you cannot create a Document with the same name as an existing collection.");
}
try (final LockedDocument oldLockedDoc = targetCollection.getDocumentWithLock(this, newDocName, LockMode.WRITE_LOCK)) {
final DocumentTrigger trigger = new DocumentTriggers(this, transaction, targetCollection);
final DocumentImpl oldDoc = oldLockedDoc == null ? null : oldLockedDoc.getDocument();
if (oldDoc == null) {
if (!targetCollection.getPermissionsNoLock().validate(getCurrentSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' does not have write access on the destination collection '" + targetCollectionUri + "'.");
}
} else {
if (sourceDocument.getDocId() == oldDoc.getDocId()) {
throw new PermissionDeniedException("Cannot copy resource to itself '" + sourceDocumentUri + "'.");
}
if (!oldDoc.getPermissions().validate(getCurrentSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("A resource with the same name already exists in the target collection '" + oldDoc.getURI() + "', and you do not have write access on that resource.");
}
trigger.beforeDeleteDocument(this, transaction, oldDoc);
trigger.afterDeleteDocument(this, transaction, targetDocumentUri);
}
doCopyDocument(transaction, trigger, sourceDocument, targetCollection, newDocName, oldDoc, preserve);
}
}
use of org.exist.collections.Collection in project exist by eXist-db.
the class NativeBroker method readCollectionEntry.
@Override
public void readCollectionEntry(final SubCollectionEntry entry) throws IOException, LockException {
final XmldbURI uri = prepend(entry.getUri().toCollectionPathURI());
final CollectionCache collectionsCache = pool.getCollectionsCache();
final Collection collection = collectionsCache.getIfPresent(uri);
if (collection == null) {
try (final ManagedLock<ReentrantLock> collectionsDbLock = lockManager.acquireBtreeReadLock(collectionsDb.getLockName())) {
final Value key = new CollectionStore.CollectionKey(uri.toString());
final VariableByteInput is = collectionsDb.getAsStream(key);
if (is == null) {
throw new IOException("Could not find collection entry for: " + uri);
}
// read the entry details
entry.read(is);
}
} else {
if (!collection.getURI().equalsInternal(uri)) {
throw new IOException(String.format("readCollectionEntry: The Collection received from the cache: %s is not the requested: %s", collection.getURI(), uri));
}
entry.read(collection);
}
}
Aggregations