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);
}
}
}
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);
}
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;
}
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;
}
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;
}
Aggregations