Search in sources :

Example 31 with XmldbURI

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;
}
Also used : Collection(org.exist.collections.Collection) LockMode(org.exist.storage.lock.Lock.LockMode) XmldbURI(org.exist.xmldb.XmldbURI)

Example 32 with XmldbURI

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;
}
Also used : Txn(org.exist.storage.txn.Txn) TerminatedException(org.exist.xquery.TerminatedException) XMLStreamException(javax.xml.stream.XMLStreamException) SAXException(org.xml.sax.SAXException) EXistException(org.exist.EXistException) TransactionException(org.exist.storage.txn.TransactionException) TransactionManager(org.exist.storage.txn.TransactionManager) Collection(org.exist.collections.Collection) DOMIndexer(org.exist.dom.memtree.DOMIndexer) XmldbURI(org.exist.xmldb.XmldbURI)

Example 33 with XmldbURI

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);
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) VariableByteInput(org.exist.storage.io.VariableByteInput) XmldbURI(org.exist.xmldb.XmldbURI) TerminatedException(org.exist.xquery.TerminatedException)

Example 34 with XmldbURI

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);
    }
}
Also used : Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI)

Example 35 with XmldbURI

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();
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) Nullable(javax.annotation.Nullable)

Aggregations

XmldbURI (org.exist.xmldb.XmldbURI)260 Collection (org.exist.collections.Collection)100 PermissionDeniedException (org.exist.security.PermissionDeniedException)69 Test (org.junit.Test)56 Txn (org.exist.storage.txn.Txn)55 EXistException (org.exist.EXistException)42 URISyntaxException (java.net.URISyntaxException)39 LockedDocument (org.exist.dom.persistent.LockedDocument)39 IOException (java.io.IOException)38 DBBroker (org.exist.storage.DBBroker)38 DocumentImpl (org.exist.dom.persistent.DocumentImpl)34 SAXException (org.xml.sax.SAXException)33 Permission (org.exist.security.Permission)30 LockException (org.exist.util.LockException)27 Path (java.nio.file.Path)22 XPathException (org.exist.xquery.XPathException)22 BrokerPool (org.exist.storage.BrokerPool)21 TransactionManager (org.exist.storage.txn.TransactionManager)20 Subject (org.exist.security.Subject)19 StringInputSource (org.exist.util.StringInputSource)17