use of org.exist.storage.txn.Txn 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.storage.txn.Txn in project exist by eXist-db.
the class Deployment method deploy.
public Optional<String> deploy(final DBBroker broker, final Txn transaction, final String pkgName, final Optional<ExistRepository> repo, final String userTarget) throws PackageException, IOException {
final Optional<Path> maybePackageDir = getPackageDir(pkgName, repo);
if (!maybePackageDir.isPresent()) {
throw new PackageException("Package not found: " + pkgName);
}
final Path packageDir = maybePackageDir.get();
final DocumentImpl repoXML = getRepoXML(broker, packageDir);
if (repoXML == null) {
return Optional.empty();
}
try {
// if there's a <setup> element, run the query it points to
final Optional<ElementImpl> setup = findElement(repoXML, SETUP_ELEMENT);
final Optional<String> setupPath = setup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
if (setupPath.isPresent()) {
runQuery(broker, null, packageDir, setupPath.get(), pkgName, QueryPurpose.SETUP);
return Optional.empty();
} else {
// otherwise create the target collection
XmldbURI targetCollection = null;
if (userTarget != null) {
try {
targetCollection = XmldbURI.create(userTarget);
} catch (final IllegalArgumentException e) {
throw new PackageException("Bad collection URI: " + userTarget, e);
}
} else {
final Optional<ElementImpl> target = findElement(repoXML, TARGET_COLL_ELEMENT);
final Optional<String> targetPath = target.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
if (targetPath.isPresent()) {
// determine target collection
try {
targetCollection = XmldbURI.create(getTargetCollection(broker, targetPath.get()));
} catch (final IllegalArgumentException e) {
throw new PackageException("Bad collection URI for <target> element: " + targetPath.get(), e);
}
} else {
LOG.warn("EXPath Package '{}' does not contain a <target> in its repo.xml, no files will be deployed to /apps", pkgName);
}
}
if (targetCollection == null) {
// no target means: package does not need to be deployed into database
// however, we need to preserve a copy for backup purposes
final Optional<Package> pkg = getPackage(pkgName, repo);
pkg.orElseThrow(() -> new XPathException("expath repository is not available so the package was not stored."));
final String pkgColl = pkg.get().getAbbrev() + "-" + pkg.get().getVersion();
targetCollection = XmldbURI.SYSTEM.append("repo/" + pkgColl);
}
// extract the permissions (if any)
final Optional<ElementImpl> permissions = findElement(repoXML, PERMISSIONS_ELEMENT);
final Optional<RequestedPerms> requestedPerms = permissions.flatMap(elem -> {
final Optional<Either<Integer, String>> perms = Optional.ofNullable(elem.getAttribute("mode")).flatMap(mode -> {
try {
return Optional.of(Either.Left(Integer.parseInt(mode, 8)));
} catch (final NumberFormatException e) {
if (mode.matches("^[rwx-]{9}")) {
return Optional.of(Either.Right(mode));
} else {
return Optional.empty();
}
}
});
return perms.map(p -> new RequestedPerms(elem.getAttribute("user"), elem.getAttribute("password"), Optional.ofNullable(elem.getAttribute("group")), p));
});
// check that if there were permissions then we were able to parse them, a failure would be related to the mode string
if (permissions.isPresent() && !requestedPerms.isPresent()) {
final String mode = permissions.map(elem -> elem.getAttribute("mode")).orElse(null);
throw new PackageException("Bad format for mode attribute in <permissions>: " + mode);
}
// run the pre-setup query if present
final Optional<ElementImpl> preSetup = findElement(repoXML, PRE_SETUP_ELEMENT);
final Optional<String> preSetupPath = preSetup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
if (preSetupPath.isPresent()) {
runQuery(broker, targetCollection, packageDir, preSetupPath.get(), pkgName, QueryPurpose.PREINSTALL);
}
// TODO: if the user already exists, check and ensure the user is assigned to the specified group
if (requestedPerms.isPresent()) {
checkUserSettings(broker, requestedPerms.get());
}
final InMemoryNodeSet resources = findElements(repoXML, RESOURCES_ELEMENT);
// store all package contents into database, using the user/group/mode in the permissions element. however:
// 1. repo.xml is excluded for now, since it may contain the default user's password in the clear
// 2. contents of directories identified in the path attribute of any <resource path=""/> element are stored as binary
final List<String> errors = scanDirectory(broker, transaction, packageDir, targetCollection, resources, true, false, requestedPerms);
// store repo.xml, filtering out the default user's password
storeRepoXML(broker, transaction, repoXML, targetCollection, requestedPerms);
// run the post-setup query if present
final Optional<ElementImpl> postSetup = findElement(repoXML, POST_SETUP_ELEMENT);
final Optional<String> postSetupPath = postSetup.map(ElementImpl::getStringValue).filter(s -> !s.isEmpty());
if (postSetupPath.isPresent()) {
runQuery(broker, targetCollection, packageDir, postSetupPath.get(), pkgName, QueryPurpose.POSTINSTALL);
}
if (!errors.isEmpty()) {
throw new PackageException("Deployment incomplete, " + errors.size() + " issues found: " + String.join("; ", errors));
}
return Optional.ofNullable(targetCollection.getCollectionPath());
}
} catch (final XPathException e) {
throw new PackageException("Error found while processing repo.xml: " + e.getMessage(), e);
}
}
use of org.exist.storage.txn.Txn 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.storage.txn.Txn in project exist by eXist-db.
the class AbstractLocal method withDb.
/**
* Higher-order-function for performing an XMLDB operation on
* the database
*
* @param dbOperation The operation to perform on the database
* @param <R> The return type of the operation
*
* @return the result of the operation
*
* @throws XMLDBException if an error occurs when executing the operation.
*/
protected <R> R withDb(final LocalXmldbFunction<R> dbOperation) throws XMLDBException {
try (final DBBroker broker = brokerPool.get(Optional.ofNullable(user));
final Txn transaction = transaction().apply(broker)) {
try {
final R result = dbOperation.apply(broker, transaction);
transaction.commit();
return result;
} catch (final XMLDBException | EXistException e) {
transaction.abort();
throw e;
}
} catch (final EXistException e) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
}
}
use of org.exist.storage.txn.Txn in project exist by eXist-db.
the class IndexerTest2 method storeDoc.
private static void storeDoc() throws PermissionDeniedException, IOException, EXistException, SAXException, LockException, AuthenticationException {
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
final TransactionManager txnMgr = pool.getTransactionManager();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().authenticate("admin", "")));
final Txn txn = txnMgr.beginTransaction()) {
try (final Collection collection = broker.getOrCreateCollection(txn, TestConstants.TEST_COLLECTION_URI)) {
broker.storeDocument(txn, TestConstants.TEST_XML_URI2, new StringInputSource(XML), MimeType.XML_TYPE, collection);
broker.flush();
broker.saveCollection(txn, collection);
}
txnMgr.commit(txn);
}
}
Aggregations