Search in sources :

Example 26 with Collection

use of org.exist.collections.Collection in project exist by eXist-db.

the class NativeBroker method getResource.

@Override
public DocumentImpl getResource(XmldbURI fileName, final int accessType) throws PermissionDeniedException {
    fileName = prepend(fileName.toCollectionPathURI());
    // TODO : resolve URIs !!!
    final XmldbURI collUri = fileName.removeLastSegment();
    final XmldbURI docUri = fileName.lastSegment();
    try (final Collection collection = openCollection(collUri, LockMode.READ_LOCK)) {
        if (collection == null) {
            LOG.debug("collection '{}' not found!", collUri);
            return null;
        }
        try (final LockedDocument lockedDocument = collection.getDocumentWithLock(this, docUri, LockMode.READ_LOCK)) {
            // NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
            collection.close();
            if (lockedDocument == null) {
                LOG.debug("document '{}' not found!", fileName);
                return null;
            }
            final DocumentImpl doc = lockedDocument.getDocument();
            if (!doc.getPermissions().validate(getCurrentSubject(), accessType)) {
                throw new PermissionDeniedException("Account '" + getCurrentSubject().getName() + "' not allowed requested access to document '" + fileName + "'");
            }
            return doc;
        } catch (final LockException e) {
            throw new PermissionDeniedException(e);
        }
    }
}
Also used : Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI)

Example 27 with Collection

use of org.exist.collections.Collection in project exist by eXist-db.

the class NativeBroker method moveResource.

@Override
public void moveResource(final Txn transaction, final DocumentImpl sourceDocument, final Collection targetCollection, final XmldbURI newName) throws PermissionDeniedException, LockException, IOException, TriggerException {
    assert (sourceDocument != null);
    assert (targetCollection != null);
    assert (newName != null);
    if (isReadOnly()) {
        throw new IOException(DATABASE_IS_READ_ONLY);
    }
    if (newName.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 destinationDocumentUri = targetCollectionUri.append(newName);
    final Account docUser = sourceDocument.getUserLock();
    if (docUser != null) {
        if (!getCurrentSubject().getName().equals(docUser.getName())) {
            throw new PermissionDeniedException("Cannot move '" + sourceDocumentUri + " because is locked by getUser() '" + docUser.getName() + "'");
        }
    }
    /**
     * As per the rules of Linux -
     *
     * mv is NOT a copy operation unless we are traversing filesystems.
     * We consider eXist to be a single filesystem, so we only need
     * WRITE and EXECUTE access on the source and destination collections
     * as we are effectively just re-linking the file.
     *
     * - Adam 2013-03-26
     */
    // we assume the caller holds a WRITE_LOCK on sourceDocument#getCollection()
    final Collection sourceCollection = sourceDocument.getCollection();
    if (!sourceCollection.getPermissionsNoLock().validate(getCurrentSubject(), Permission.WRITE | Permission.EXECUTE)) {
        throw new PermissionDeniedException("Account " + getCurrentSubject().getName() + " have insufficient privileges on source Collection to move resource: " + sourceDocumentUri);
    }
    if (!targetCollection.getPermissionsNoLock().validate(getCurrentSubject(), Permission.WRITE | Permission.EXECUTE)) {
        throw new PermissionDeniedException("Account " + getCurrentSubject().getName() + " have insufficient privileges on destination Collection '" + targetCollectionUri + "' to move resource: " + sourceDocumentUri);
    }
    if (targetCollection.hasChildCollection(this, newName.lastSegment())) {
        throw new PermissionDeniedException("The Collection '" + targetCollectionUri + "' has a sub-collection '" + newName + "'; cannot create a Document with the same name!");
    }
    final DocumentTrigger trigger = new DocumentTriggers(this, transaction, sourceCollection);
    // check if the move would overwrite a document
    final DocumentImpl oldDoc = targetCollection.getDocument(this, newName);
    if (oldDoc != null) {
        if (sourceDocument.getDocId() == oldDoc.getDocId()) {
            throw new PermissionDeniedException("Cannot move resource to itself '" + sourceDocumentUri + "'.");
        }
        // GNU mv command would prompt for Confirmation here, you can say yes or pass the '-f' flag. As we cant prompt for confirmation we assume OK
        /* if(!oldDoc.getPermissions().validate(getCurrentSubject(), Permission.WRITE)) {
                throw new PermissionDeniedException("Resource with same name exists in target collection and write is denied");
            }
            */
        // remove the existing document
        removeResource(transaction, oldDoc);
    }
    final boolean renameOnly = sourceCollection.getId() == targetCollection.getId();
    trigger.beforeMoveDocument(this, transaction, sourceDocument, destinationDocumentUri);
    if (sourceDocument.getResourceType() == DocumentImpl.XML_FILE) {
        if (!renameOnly) {
            dropIndex(transaction, sourceDocument);
        }
    }
    sourceCollection.unlinkDocument(this, sourceDocument);
    if (!renameOnly) {
        saveCollection(transaction, sourceCollection);
    }
    removeResourceMetadata(transaction, sourceDocument);
    sourceDocument.setFileURI(newName);
    sourceDocument.setCollection(targetCollection);
    targetCollection.addDocument(transaction, this, sourceDocument);
    if (sourceDocument.getResourceType() == DocumentImpl.XML_FILE) {
        if (!renameOnly) {
            // reindexing
            reindexXMLResource(transaction, sourceDocument, IndexMode.REPAIR);
        }
    }
    // NOTE: nothing needs to be done for binary resources as the reference to the Blob does not change
    storeXMLResource(transaction, sourceDocument);
    saveCollection(transaction, targetCollection);
    trigger.afterMoveDocument(this, transaction, sourceDocument, sourceDocumentUri);
}
Also used : Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI)

Example 28 with Collection

use of org.exist.collections.Collection in project exist by eXist-db.

the class NativeValueIndex method findAll.

/**
 * find.
 *
 * @param comparison The type of comparison the search is performing
 * @param docs       The documents to search for matches within
 * @param contextSet DOCUMENT ME!
 * @param axis       DOCUMENT ME!
 * @param qnames     DOCUMENT ME!
 * @param value      right hand comparison value
 * @param result     DOCUMENT ME!
 * @return DOCUMENT ME!
 * @throws TerminatedException DOCUMENT ME!
 */
private NodeSet findAll(final XQueryWatchDog watchDog, final Comparison comparison, final DocumentSet docs, final NodeSet contextSet, final int axis, final List<QName> qnames, final Indexable value, final NodeSet result) throws TerminatedException {
    final SearchCallback cb = new SearchCallback(docs, contextSet, result, axis == NodeSet.ANCESTOR);
    final int idxOp = toIndexQueryOp(comparison);
    for (final Iterator<Collection> iter = docs.getCollectionIterator(); iter.hasNext(); ) {
        final int collectionId = iter.next().getId();
        watchDog.proceed(null);
        if (qnames == null) {
            try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                final Value searchKey = new SimpleValue(collectionId, value);
                final IndexQuery query = new IndexQuery(idxOp, searchKey);
                if (idxOp == IndexQuery.EQ) {
                    dbValues.query(query, cb);
                } else {
                    final Value prefixKey = new SimplePrefixValue(collectionId, value.getType());
                    dbValues.query(query, prefixKey, cb);
                }
            } catch (final EXistException | BTreeException | IOException e) {
                LOG.error(e.getMessage(), e);
            } catch (final LockException e) {
                LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
            }
        } else {
            for (final QName qname : qnames) {
                try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                    // Compute a key for the value in the collection
                    final Value searchKey = new QNameValue(collectionId, qname, value, broker.getBrokerPool().getSymbols());
                    final IndexQuery query = new IndexQuery(idxOp, searchKey);
                    if (idxOp == IndexQuery.EQ) {
                        dbValues.query(query, cb);
                    } else {
                        final Value prefixKey = new QNamePrefixValue(collectionId, qname, value.getType(), broker.getBrokerPool().getSymbols());
                        dbValues.query(query, prefixKey, cb);
                    }
                } catch (final EXistException | BTreeException | IOException e) {
                    LOG.error(e.getMessage(), e);
                } catch (final LockException e) {
                    LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
                }
            }
        }
    }
    return result;
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) IndexQuery(org.exist.storage.btree.IndexQuery) QName(org.exist.dom.QName) EXistException(org.exist.EXistException) IOException(java.io.IOException) BTreeException(org.exist.storage.btree.BTreeException) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value) Collection(org.exist.collections.Collection)

Example 29 with Collection

use of org.exist.collections.Collection in project exist by eXist-db.

the class NativeValueIndex method getDefinedIndexes.

private List<QName> getDefinedIndexes(final DocumentSet docs) {
    final List<QName> qnames = new ArrayList<>();
    for (final Iterator<Collection> i = docs.getCollectionIterator(); i.hasNext(); ) {
        final Collection collection = i.next();
        final IndexSpec idxConf = collection.getIndexConfiguration(broker);
        if (idxConf != null) {
            qnames.addAll(idxConf.getIndexedQNames());
        }
    }
    return qnames;
}
Also used : QName(org.exist.dom.QName) Collection(org.exist.collections.Collection)

Example 30 with Collection

use of org.exist.collections.Collection in project exist by eXist-db.

the class NativeValueIndex method matchAll.

/**
 * Regular expression search.
 *
 * @param docs               DOCUMENT ME!
 * @param contextSet         DOCUMENT ME!
 * @param axis               DOCUMENT ME!
 * @param expr               DOCUMENT ME!
 * @param qnames             DOCUMENT ME!
 * @param type               like type argument for {@link org.exist.storage.RegexMatcher} constructor
 * @param flags              like flags argument for {@link org.exist.storage.RegexMatcher} constructor
 * @param caseSensitiveQuery DOCUMENT ME!
 * @param result             DOCUMENT ME!
 * @param collator           DOCUMENT ME!
 * @param truncation         The type of string truncation to apply
 * @param watchDog  the watchdog
 * @return DOCUMENT ME!
 * @throws TerminatedException DOCUMENT ME!
 * @throws EXistException      DOCUMENT ME!
 */
public NodeSet matchAll(final XQueryWatchDog watchDog, final DocumentSet docs, final NodeSet contextSet, final int axis, final String expr, final List<QName> qnames, final int type, final int flags, final boolean caseSensitiveQuery, final NodeSet result, final Collator collator, final StringTruncationOperator truncation) throws TerminatedException, EXistException {
    // if the match expression starts with a char sequence, we restrict the index scan to entries starting with
    // the same sequence. Otherwise, we have to scan the whole index.
    final StringValue startTerm;
    if (type == DBBroker.MATCH_REGEXP && expr.startsWith("^") && caseSensitiveQuery == caseSensitive) {
        final StringBuilder term = new StringBuilder();
        for (int j = 1; j < expr.length(); j++) {
            if (Character.isLetterOrDigit(expr.charAt(j))) {
                term.append(expr.charAt(j));
            } else {
                break;
            }
        }
        if (term.length() > 0) {
            startTerm = new StringValue(term.toString());
            LOG.debug("Match will begin index scan at '{}'", startTerm);
        } else {
            startTerm = null;
        }
    } else if (collator == null && (type == DBBroker.MATCH_EXACT || type == DBBroker.MATCH_STARTSWITH)) {
        startTerm = new StringValue(expr);
        LOG.debug("Match will begin index scan at '{}'", startTerm);
    } else {
        startTerm = null;
    }
    // Select appropriate matcher/comparator
    final TermMatcher matcher;
    if (collator == null) {
        switch(type) {
            case DBBroker.MATCH_EXACT:
                matcher = new ExactMatcher(expr);
                break;
            case DBBroker.MATCH_CONTAINS:
                matcher = new ContainsMatcher(expr);
                break;
            case DBBroker.MATCH_STARTSWITH:
                matcher = new StartsWithMatcher(expr);
                break;
            case DBBroker.MATCH_ENDSWITH:
                matcher = new EndsWithMatcher(expr);
                break;
            default:
                matcher = new RegexMatcher(expr, flags);
        }
    } else {
        matcher = new CollatorMatcher(expr, truncation, collator);
    }
    final MatcherCallback cb = new MatcherCallback(docs, contextSet, result, matcher, axis == NodeSet.ANCESTOR);
    for (final Iterator<Collection> iter = docs.getCollectionIterator(); iter.hasNext(); ) {
        final int collectionId = iter.next().getId();
        watchDog.proceed(null);
        if (qnames == null) {
            try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                final Value searchKey;
                if (startTerm != null) {
                    // Compute a key for the start term in the collection
                    searchKey = new SimpleValue(collectionId, startTerm);
                } else {
                    // Compute a key for an arbitrary string in the collection
                    searchKey = new SimplePrefixValue(collectionId, Type.STRING);
                }
                final IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, searchKey);
                dbValues.query(query, cb);
            } catch (final IOException | BTreeException e) {
                LOG.error(e.getMessage(), e);
            } catch (final LockException e) {
                LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
            }
        } else {
            for (final QName qname : qnames) {
                try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                    final Value searchKey;
                    if (startTerm != null) {
                        searchKey = new QNameValue(collectionId, qname, startTerm, broker.getBrokerPool().getSymbols());
                    } else {
                        LOG.debug("Searching with QName prefix");
                        searchKey = new QNamePrefixValue(collectionId, qname, Type.STRING, broker.getBrokerPool().getSymbols());
                    }
                    final IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, searchKey);
                    dbValues.query(query, cb);
                } catch (final IOException | BTreeException e) {
                    LOG.error(e.getMessage(), e);
                } catch (final LockException e) {
                    LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
                }
            }
        }
    }
    return result;
}
Also used : BTreeException(org.exist.storage.btree.BTreeException) StringValue(org.exist.xquery.value.StringValue) ReentrantLock(java.util.concurrent.locks.ReentrantLock) IndexQuery(org.exist.storage.btree.IndexQuery) QName(org.exist.dom.QName) IOException(java.io.IOException) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value) Collection(org.exist.collections.Collection)

Aggregations

Collection (org.exist.collections.Collection)297 Txn (org.exist.storage.txn.Txn)160 XmldbURI (org.exist.xmldb.XmldbURI)99 DBBroker (org.exist.storage.DBBroker)89 TransactionManager (org.exist.storage.txn.TransactionManager)86 BrokerPool (org.exist.storage.BrokerPool)69 StringInputSource (org.exist.util.StringInputSource)57 Test (org.junit.Test)57 EXistException (org.exist.EXistException)43 PermissionDeniedException (org.exist.security.PermissionDeniedException)43 DocumentImpl (org.exist.dom.persistent.DocumentImpl)42 IOException (java.io.IOException)33 LockedDocument (org.exist.dom.persistent.LockedDocument)31 SAXException (org.xml.sax.SAXException)26 InputStream (java.io.InputStream)19 Path (java.nio.file.Path)19 Permission (org.exist.security.Permission)19 LockException (org.exist.util.LockException)16 TriggerException (org.exist.collections.triggers.TriggerException)15 BinaryDocument (org.exist.dom.persistent.BinaryDocument)15