use of org.exist.xmldb.XmldbURI in project exist by eXist-db.
the class NativeBroker method getXMLResource.
@Override
public LockedDocument getXMLResource(XmldbURI fileName, final LockMode lockMode) throws PermissionDeniedException {
if (fileName == null) {
return null;
}
fileName = prepend(fileName.toCollectionPathURI());
// TODO : resolve URIs !
final XmldbURI collUri = fileName.removeLastSegment();
final XmldbURI docUri = fileName.lastSegment();
final LockMode collectionLockMode = lockManager.relativeCollectionLockMode(LockMode.READ_LOCK, lockMode);
try (final Collection collection = openCollection(collUri, collectionLockMode)) {
if (collection == null) {
LOG.debug("Collection '{}' not found!", collUri);
return null;
}
try {
// if (!collection.getPermissions().validate(getCurrentSubject(), Permission.EXECUTE)) {
// throw new PermissionDeniedException("Permission denied to read collection '" + collUri + "' by " + getCurrentSubject().getName());
// }
final LockedDocument lockedDocument = collection.getDocumentWithLock(this, docUri, lockMode);
// NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
collection.close();
if (lockedDocument == null) {
// LOG.debug("document '" + fileName + "' not found!");
return null;
}
// if (!doc.getMode().validate(getUser(), Permission.READ))
// throw new PermissionDeniedException("not allowed to read document");
final DocumentImpl doc = lockedDocument.getDocument();
return lockedDocument;
} catch (final LockException e) {
LOG.error("Could not acquire lock on document {}", fileName, e);
// TODO : exception ? -pb
}
}
return null;
}
use of org.exist.xmldb.XmldbURI in project exist by eXist-db.
the class NativeBroker method storeTempResource.
/**
* Store into the temporary collection of the database a given in-memory Document
*
* The in-memory Document is stored without a transaction and is not journalled,
* if there is no temporary collection, this will first be created with a transaction
*
* @param doc The in-memory Document to store
* @return The document stored in the temp collection
*/
@Override
public DocumentImpl storeTempResource(final org.exist.dom.memtree.DocumentImpl doc) throws EXistException, PermissionDeniedException, LockException {
try {
// elevate getUser() to DBA_USER
pushSubject(pool.getSecurityManager().getSystemSubject());
// start a transaction
final TransactionManager transact = pool.getTransactionManager();
// create a name for the temporary document
final XmldbURI docName = XmldbURI.create(MessageDigester.md5(Thread.currentThread().getName() + System.currentTimeMillis(), false) + ".xml");
// get the temp collection
try (final Txn transaction = transact.beginTransaction();
final ManagedCollectionLock tempCollectionLock = lockManager.acquireCollectionWriteLock(XmldbURI.TEMP_COLLECTION_URI)) {
// if temp collection does not exist, creates temp collection (with write lock in Txn)
final Tuple2<Boolean, Collection> createdOrExistingTemp = getOrCreateTempCollection(transaction);
if (createdOrExistingTemp == null) {
LOG.error("Failed to create temporary collection");
transact.abort(transaction);
return null;
}
final Collection temp = createdOrExistingTemp._2;
// create a temporary document
try (final ManagedDocumentLock docLock = lockManager.acquireDocumentWriteLock(temp.getURI().append(docName))) {
final int tmpDocId = getNextResourceId(transaction);
final Permission permission = PermissionFactory.getDefaultResourcePermission(getBrokerPool().getSecurityManager());
permission.setMode(Permission.DEFAULT_TEMPORARY_DOCUMENT_PERM);
final DocumentImpl targetDoc = new DocumentImpl(pool, temp, tmpDocId, docName, permission, 0, null, System.currentTimeMillis(), null, null, null);
// index the temporary document
final DOMIndexer indexer = new DOMIndexer(this, transaction, doc, targetDoc);
indexer.scan();
indexer.store();
// store the temporary document
temp.addDocument(transaction, this, targetDoc);
storeXMLResource(transaction, targetDoc);
saveCollection(transaction, temp);
// NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
temp.close();
flush();
closeDocument();
// commit the transaction
transact.commit(transaction);
return targetDoc;
}
} catch (final Exception e) {
LOG.error("Failed to store temporary fragment: {}", e.getMessage(), e);
}
} finally {
// restore the user
popSubject();
}
return null;
}
use of org.exist.xmldb.XmldbURI in project exist by eXist-db.
the class NativeBroker method getResourceById.
@Override
public DocumentImpl getResourceById(final int collectionId, final byte resourceType, final int documentId) throws PermissionDeniedException {
XmldbURI uri;
try (final ManagedLock<ReentrantLock> collectionsDbLock = lockManager.acquireBtreeReadLock(collectionsDb.getLockName())) {
// get the collection uri
String collectionUri = null;
if (collectionId == FIRST_COLLECTION_ID) {
collectionUri = "/db";
} else {
for (final Value collectionDbKey : collectionsDb.getKeys()) {
final byte[] data = collectionDbKey.data();
if (data[0] == CollectionStore.KEY_TYPE_COLLECTION) {
// Value collectionDbValue = collectionsDb.get(collectionDbKey);
final VariableByteInput vbi = collectionsDb.getAsStream(collectionDbKey);
final int id = vbi.readInt();
// check if the collection id matches (first 4 bytes)
if (collectionId == id) {
collectionUri = new String(Arrays.copyOfRange(data, 1, data.length));
break;
}
}
}
}
// get the resource uri
final Value key = new CollectionStore.DocumentKey(collectionId, resourceType, documentId);
final VariableByteInput vbi = collectionsDb.getAsStream(key);
// skip doc id
vbi.readInt();
final String resourceUri = vbi.readUTF();
// get the resource
uri = XmldbURI.createInternal(collectionUri + "/" + resourceUri);
} catch (final TerminatedException te) {
LOG.error("Query Terminated", te);
return null;
} catch (final BTreeException bte) {
LOG.error("Problem reading btree", bte);
return null;
} catch (final LockException e) {
LOG.error("Failed to acquire lock on {}", FileUtils.fileName(collectionsDb.getFile()));
return null;
} catch (final IOException e) {
LOG.error("IOException while reading resource data", e);
return null;
}
return getResource(uri, Permission.READ);
}
use of org.exist.xmldb.XmldbURI in project exist by eXist-db.
the class NativeBroker method reindexCollection.
private void reindexCollection(final Txn transaction, @EnsureLocked(mode = LockMode.READ_LOCK) final Collection collection, final IndexMode mode) throws PermissionDeniedException, IOException, LockException {
if (!collection.getPermissionsNoLock().validate(getCurrentSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("Account " + getCurrentSubject().getName() + " have insufficient privileges on collection " + collection.getURI());
}
LOG.debug("Reindexing collection {}", collection.getURI());
if (mode == IndexMode.STORE) {
dropCollectionIndex(transaction, collection, true);
}
// reindex documents
try {
for (final Iterator<DocumentImpl> i = collection.iterator(this); i.hasNext(); ) {
final DocumentImpl next = i.next();
reindexXMLResource(transaction, next, mode);
}
} catch (final LockException e) {
LOG.error("LockException while reindexing documents of collection '{}'. Skipping...", collection.getURI(), e);
}
// descend into child collections
try {
for (final Iterator<XmldbURI> i = collection.collectionIterator(this); i.hasNext(); ) {
final XmldbURI childName = i.next();
final XmldbURI childUri = collection.getURI().append(childName);
try (final Collection child = openCollection(childUri, LockMode.READ_LOCK)) {
if (child == null) {
throw new IOException("Collection '" + childUri + "' not found");
} else {
reindexCollection(transaction, child, mode);
}
}
}
} catch (final LockException e) {
LOG.error("LockException while reindexing child collections of collection '{}'. Skipping...", collection.getURI(), e);
}
}
use of org.exist.xmldb.XmldbURI in project exist by eXist-db.
the class NativeBroker method _removeCollection.
private boolean _removeCollection(final Txn transaction, @EnsureLocked(mode = LockMode.WRITE_LOCK) final Collection collection) throws PermissionDeniedException, TriggerException, IOException {
final XmldbURI collectionUri = collection.getURI();
getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_REMOVE_COLLECTION, collectionUri);
try {
// NOTE: we already have a WRITE lock on the parent of the Collection we set out to remove
@Nullable final Collection parentCollection = collection.getParentURI() == null ? null : getCollection(collection.getParentURI());
// TODO(AR) the below permissions check could be optimised when descending the tree so we don't check the same collection(s) twice in some cases
if (!checkRemoveCollectionPermissions(parentCollection, collection)) {
throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' is not allowed to remove collection '" + collection.getURI() + "'");
}
final CollectionTrigger colTrigger = new CollectionTriggers(this, transaction, parentCollection == null ? collection : parentCollection);
colTrigger.beforeDeleteCollection(this, transaction, collection);
// 2) remove descendant collections
for (final Iterator<XmldbURI> subCollectionName = collection.collectionIteratorNoLock(this); subCollectionName.hasNext(); ) {
// NOTE: we already have a WRITE lock on the parent of the Collection we set out to remove
final XmldbURI subCollectionUri = collectionUri.append(subCollectionName.next());
// NOTE: we already have a WRITE lock on the parent of the Collection we set out to remove
final boolean removedSubCollection = _removeCollection(transaction, getCollection(subCollectionUri));
if (!removedSubCollection) {
LOG.error("Unable to remove Collection: {}", subCollectionUri);
return false;
}
}
// TODO(AR) this can be executed asynchronously as a task, Do we need to await the completion before unlocking the collection? or just await completion before returning from the first call to _removeCollection?
// 3) drop indexes for this Collection
notifyDropIndex(collection);
getIndexController().removeCollection(collection, this, false);
// 4) remove this Collection from the parent Collection
if (parentCollection != null) {
parentCollection.removeCollection(this, collectionUri.lastSegment());
saveCollection(transaction, parentCollection);
}
// 5) remove Collection from collections.dbx
if (parentCollection != null) {
try (final ManagedLock<ReentrantLock> collectionsDbLock = lockManager.acquireBtreeWriteLock(collectionsDb.getLockName())) {
final Value key = new CollectionStore.CollectionKey(collectionUri.getRawCollectionPath());
collectionsDb.remove(transaction, key);
// TODO(AR) is this the correct place to invalidate the config?
// Notify the collection configuration manager
final CollectionConfigurationManager manager = pool.getConfigurationManager();
if (manager != null) {
manager.invalidate(collectionUri, getBrokerPool());
}
}
// invalidate the cache entry
final CollectionCache collectionsCache = pool.getCollectionsCache();
collectionsCache.invalidate(collection.getURI());
} else {
// if this is the root collection we just have to save
// it to persist the removal of any subCollections to collections.dbx
saveCollection(transaction, collection);
}
// 6) unlink all documents from the Collection
try (final ManagedLock<ReentrantLock> collectionsDbLock = lockManager.acquireBtreeWriteLock(collectionsDb.getLockName())) {
final Value docKey = new CollectionStore.DocumentKey(collection.getId());
final IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, docKey);
collectionsDb.removeAll(transaction, query);
if (parentCollection != null) {
// we must not free the root collection id!
collectionsDb.freeCollectionId(collection.getId());
}
} catch (final BTreeException | IOException e) {
LOG.error("Unable to unlink documents from the Collection: {}", collectionUri, e);
}
// TODO(AR) this can be executed asynchronously as a task, we need to await the completion before unlocking the collection
// 7) remove the documents nodes and binary documents of the Collection from dom.dbx
removeCollectionsDocumentNodes(transaction, collection);
colTrigger.afterDeleteCollection(this, transaction, collectionUri);
return true;
} catch (final LockException e) {
LOG.error("Unable to lock Collection: {}", collectionUri, e);
return false;
} finally {
getBrokerPool().getProcessMonitor().endJob();
}
}
Aggregations