Search in sources :

Example 41 with Txn

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;
}
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 42 with Txn

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);
    }
}
Also used : Path(java.nio.file.Path) DependencyVersion(org.expath.pkg.repo.deps.DependencyVersion) Txn(org.exist.storage.txn.Txn) java.util(java.util) BufferedInputStream(java.io.BufferedInputStream) QName(org.exist.dom.QName) SequenceIterator(org.exist.xquery.value.SequenceIterator) PermissionDeniedException(org.exist.security.PermissionDeniedException) org.exist.xquery(org.exist.xquery) DirectoryStream(java.nio.file.DirectoryStream) JarEntry(java.util.jar.JarEntry) org.exist.dom.memtree(org.exist.dom.memtree) Collection(org.exist.collections.Collection) UnixStylePermission(org.exist.security.UnixStylePermission) XmldbURI(org.exist.xmldb.XmldbURI) Attributes(org.xml.sax.Attributes) JarInputStream(java.util.jar.JarInputStream) EXistException(org.exist.EXistException) DocUtils(org.exist.xquery.util.DocUtils) DateTimeValue(org.exist.xquery.value.DateTimeValue) SystemProperties(org.exist.SystemProperties) Path(java.nio.file.Path) Permission(org.exist.security.Permission) Nullable(javax.annotation.Nullable) BatchUserInteraction(org.expath.pkg.repo.tui.BatchUserInteraction) PermissionFactory(org.exist.security.PermissionFactory) InputSource(org.xml.sax.InputSource) Files(java.nio.file.Files) GroupAider(org.exist.security.internal.aider.GroupAider) Type(org.exist.xquery.value.Type) FileSource(org.exist.source.FileSource) IOException(java.io.IOException) UserAider(org.exist.security.internal.aider.UserAider) Either(com.evolvedbinary.j8fu.Either) org.expath.pkg.repo(org.expath.pkg.repo) Logger(org.apache.logging.log4j.Logger) Element(org.w3c.dom.Element) Stream(java.util.stream.Stream) DBBroker(org.exist.storage.DBBroker) SAXException(org.xml.sax.SAXException) org.exist.util(org.exist.util) Sequence(org.exist.xquery.value.Sequence) TriggerException(org.exist.collections.triggers.TriggerException) LogManager(org.apache.logging.log4j.LogManager) Package(org.expath.pkg.repo.Package) AttrList(org.exist.util.serializer.AttrList) InputStream(java.io.InputStream) Either(com.evolvedbinary.j8fu.Either) Package(org.expath.pkg.repo.Package) XmldbURI(org.exist.xmldb.XmldbURI)

Example 43 with Txn

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");
        }
    }
}
Also used : Txn(org.exist.storage.txn.Txn) EXistException(org.exist.EXistException) SAXException(org.xml.sax.SAXException) DBBroker(org.exist.storage.DBBroker) TransactionManager(org.exist.storage.txn.TransactionManager) Collection(org.exist.collections.Collection) PermissionDeniedException(org.exist.security.PermissionDeniedException) XmldbURI(org.exist.xmldb.XmldbURI)

Example 44 with Txn

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);
    }
}
Also used : DBBroker(org.exist.storage.DBBroker) XMLDBException(org.xmldb.api.base.XMLDBException) Txn(org.exist.storage.txn.Txn) EXistException(org.exist.EXistException)

Example 45 with Txn

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);
    }
}
Also used : DBBroker(org.exist.storage.DBBroker) StringInputSource(org.exist.util.StringInputSource) TransactionManager(org.exist.storage.txn.TransactionManager) Collection(org.exist.collections.Collection) Txn(org.exist.storage.txn.Txn) BrokerPool(org.exist.storage.BrokerPool)

Aggregations

Txn (org.exist.storage.txn.Txn)358 DBBroker (org.exist.storage.DBBroker)215 BrokerPool (org.exist.storage.BrokerPool)179 Collection (org.exist.collections.Collection)162 TransactionManager (org.exist.storage.txn.TransactionManager)129 Sequence (org.exist.xquery.value.Sequence)84 StringInputSource (org.exist.util.StringInputSource)83 Test (org.junit.Test)80 XmldbURI (org.exist.xmldb.XmldbURI)55 EXistException (org.exist.EXistException)50 PermissionDeniedException (org.exist.security.PermissionDeniedException)38 Source (org.exist.source.Source)37 StringSource (org.exist.source.StringSource)37 DocumentImpl (org.exist.dom.persistent.DocumentImpl)35 InputSource (org.xml.sax.InputSource)33 XQuery (org.exist.xquery.XQuery)32 IOException (java.io.IOException)31 LockedDocument (org.exist.dom.persistent.LockedDocument)28 InputStream (java.io.InputStream)27 Path (java.nio.file.Path)24