use of org.exist.EXistException in project exist by eXist-db.
the class Insert method eval.
/* (non-Javadoc)
* @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
*/
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().start(this);
context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
if (contextSequence != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
}
if (contextItem != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
}
}
if (contextItem != null) {
contextSequence = contextItem.toSequence();
}
Sequence contentSeq = value.eval(contextSequence);
if (contentSeq.isEmpty()) {
throw new XPathException(this, Messages.getMessage(Error.UPDATE_EMPTY_CONTENT));
}
final Sequence inSeq = select.eval(contextSequence);
/* If we try and Insert a node at an invalid location,
* trap the error in a context variable,
* this is then accessible from xquery via. the context extension module - deliriumsky
* TODO: This trapping could be expanded further - basically where XPathException is thrown from thiss class
* TODO: Maybe we could provide more detailed messages in the trap, e.g. couldnt insert node `xyz` into `abc` becuase... this would be nicer for the end user of the xquery application
*/
if (!Type.subTypeOf(inSeq.getItemType(), Type.NODE)) {
// Indicate the failure to perform this update by adding it to the sequence in the context variable XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR
ValueSequence prevUpdateErrors = null;
final XPathException xpe = new XPathException(this, Messages.getMessage(Error.UPDATE_SELECT_TYPE));
final Object ctxVarObj = context.getAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR);
if (ctxVarObj == null) {
prevUpdateErrors = new ValueSequence();
} else {
prevUpdateErrors = (ValueSequence) XPathUtil.javaObjectToXPath(ctxVarObj, context);
}
prevUpdateErrors.add(new StringValue(xpe.getMessage()));
context.setAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR, prevUpdateErrors);
if (!inSeq.isEmpty()) {
// TODO: should we trap this instead of throwing an exception - deliriumsky?
throw xpe;
}
}
if (!inSeq.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Found: {} nodes", inSeq.getItemCount());
}
context.pushInScopeNamespaces();
contentSeq = deepCopy(contentSeq);
// start a transaction
try (final Txn transaction = getTransaction()) {
final StoredNode[] ql = selectAndLock(transaction, inSeq);
final NotificationService notifier = context.getBroker().getBrokerPool().getNotificationService();
final NodeList contentList = seq2nodeList(contentSeq);
for (final StoredNode node : ql) {
final DocumentImpl doc = node.getOwnerDocument();
if (!doc.getPermissions().validate(context.getSubject(), Permission.WRITE)) {
throw new PermissionDeniedException("User '" + context.getSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
}
// update the document
if (mode == INSERT_APPEND) {
node.appendChildren(transaction, contentList, -1);
} else {
final NodeImpl parent = (NodeImpl) getParent(node);
switch(mode) {
case INSERT_BEFORE:
parent.insertBefore(transaction, contentList, node);
break;
case INSERT_AFTER:
parent.insertAfter(transaction, contentList, node);
break;
}
}
doc.setLastModified(System.currentTimeMillis());
modifiedDocuments.add(doc);
context.getBroker().storeXMLResource(transaction, doc);
notifier.notifyUpdate(doc, UpdateListener.UPDATE);
}
finishTriggers(transaction);
// commit the transaction
transaction.commit();
} catch (final PermissionDeniedException | EXistException | LockException | TriggerException e) {
throw new XPathException(this, e.getMessage(), e);
} finally {
unlockDocuments();
context.popInScopeNamespaces();
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", Sequence.EMPTY_SEQUENCE);
}
return Sequence.EMPTY_SEQUENCE;
}
use of org.exist.EXistException in project exist by eXist-db.
the class Update method eval.
/* (non-Javadoc)
* @see org.exist.xquery.AbstractExpression#eval(org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
*/
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().start(this);
context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
if (contextSequence != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
}
if (contextItem != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
}
}
if (contextItem != null) {
contextSequence = contextItem.toSequence();
}
final Sequence contentSeq = value.eval(contextSequence);
if (contentSeq.isEmpty()) {
throw new XPathException(this, Messages.getMessage(Error.UPDATE_EMPTY_CONTENT));
}
final Sequence inSeq = select.eval(contextSequence);
/* If we try and Update a node at an invalid location,
* trap the error in a context variable,
* this is then accessible from xquery via. the context extension module - deliriumsky
* TODO: This trapping could be expanded further - basically where XPathException is thrown from thiss class
* TODO: Maybe we could provide more detailed messages in the trap, e.g. couldnt update node `xyz` into `abc` becuase... this would be nicer for the end user of the xquery application
*/
if (!Type.subTypeOf(inSeq.getItemType(), Type.NODE)) {
// Indicate the failure to perform this update by adding it to the sequence in the context variable XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR
ValueSequence prevUpdateErrors = null;
final XPathException xpe = new XPathException(this, Messages.getMessage(Error.UPDATE_SELECT_TYPE));
final Object ctxVarObj = context.getAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR);
if (ctxVarObj == null) {
prevUpdateErrors = new ValueSequence();
} else {
prevUpdateErrors = (ValueSequence) XPathUtil.javaObjectToXPath(ctxVarObj, context);
}
prevUpdateErrors.add(new StringValue(xpe.getMessage()));
context.setAttribute(XQueryContext.XQUERY_CONTEXTVAR_XQUERY_UPDATE_ERROR, prevUpdateErrors);
if (!inSeq.isEmpty()) {
// TODO: should we trap this instead of throwing an exception - deliriumsky?
throw xpe;
}
}
if (!inSeq.isEmpty()) {
context.pushInScopeNamespaces();
// start a transaction
try (final Txn transaction = getTransaction()) {
final NotificationService notifier = context.getBroker().getBrokerPool().getNotificationService();
final StoredNode[] ql = selectAndLock(transaction, inSeq);
for (final StoredNode node : ql) {
final DocumentImpl doc = node.getOwnerDocument();
if (!doc.getPermissions().validate(context.getSubject(), Permission.WRITE)) {
throw new XPathException(this, "User '" + context.getSubject().getName() + "' does not have permission to write to the document '" + doc.getDocumentURI() + "'!");
}
// update the document
switch(node.getNodeType()) {
case Node.ELEMENT_NODE:
final NodeListImpl content = new NodeListImpl();
for (final SequenceIterator j = contentSeq.iterate(); j.hasNext(); ) {
final Item next = j.nextItem();
if (Type.subTypeOf(next.getType(), Type.NODE)) {
content.add(((NodeValue) next).getNode());
} else {
final TextImpl text = new TextImpl(next.getStringValue());
content.add(text);
}
}
((ElementImpl) node).update(transaction, content);
break;
case Node.TEXT_NODE:
final ElementImpl textParent = (ElementImpl) node.getParentNode();
final TextImpl text = new TextImpl(contentSeq.getStringValue());
text.setOwnerDocument(doc);
textParent.updateChild(transaction, node, text);
break;
case Node.ATTRIBUTE_NODE:
final ElementImpl attrParent = (ElementImpl) ((Attr) node).getOwnerElement();
if (attrParent == null) {
LOG.warn("parent node not found for {}", node.getNodeId());
break;
}
final AttrImpl attr = (AttrImpl) node;
final AttrImpl attribute = new AttrImpl(attr.getQName(), contentSeq.getStringValue(), context.getBroker().getBrokerPool().getSymbols());
attribute.setOwnerDocument(doc);
attrParent.updateChild(transaction, node, attribute);
break;
default:
throw new XPathException(this, "unsupported node-type");
}
doc.setLastModified(System.currentTimeMillis());
modifiedDocuments.add(doc);
context.getBroker().storeXMLResource(transaction, doc);
notifier.notifyUpdate(doc, UpdateListener.UPDATE);
}
finishTriggers(transaction);
// commit the transaction
transaction.commit();
} catch (final LockException | EXistException | TriggerException e) {
throw new XPathException(this, e.getMessage(), e);
} finally {
unlockDocuments();
context.popInScopeNamespaces();
}
}
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", Sequence.EMPTY_SEQUENCE);
}
return Sequence.EMPTY_SEQUENCE;
}
use of org.exist.EXistException in project exist by eXist-db.
the class BinaryDocumentTest method overwriteCollection.
@Test
public void overwriteCollection() throws EXistException, PermissionDeniedException, IOException, SAXException, LockException {
final XmldbURI testCollectionUri = XmldbURI.create("/db/overwrite-collection-test");
final XmldbURI thingUri = testCollectionUri.append("thing");
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
final Txn transaction = pool.getTransactionManager().beginTransaction()) {
// create a collection
final Collection thingCollection = broker.getOrCreateCollection(transaction, thingUri);
broker.saveCollection(transaction, thingCollection);
// attempt to create a binary document with the same uri as the thingCollection (should fail)
final Collection testCollection = broker.getCollection(testCollectionUri);
try {
broker.storeDocument(transaction, thingUri.lastSegment(), new StringInputSource("binary-file".getBytes(UTF_8)), MimeType.BINARY_TYPE, testCollection);
fail("Should not have been able to overwrite Collection with Binary Document");
} catch (final EXistException e) {
assertEquals("The collection '" + testCollectionUri.getRawCollectionPath() + "' already has a sub-collection named '" + thingUri.lastSegment().toString() + "', you cannot create a Document with the same name as an existing collection.", e.getMessage());
}
}
}
use of org.exist.EXistException in project exist by eXist-db.
the class BrokerPoolsTest method shutdownConcurrent.
@Test
public void shutdownConcurrent() throws InterruptedException, ExecutionException, EXistException, DatabaseConfigurationException, IOException {
final int testThreads = 5;
final CountDownLatch shutdownLatch = new CountDownLatch(1);
final CountDownLatch acquiredLatch = new CountDownLatch(testThreads);
final List<Future<Exception>> shutdownTasks = new ArrayList<>();
final ExecutorService executorService = Executors.newFixedThreadPool(testThreads);
for (int i = 0; i < testThreads; i++) {
final Path dataDir = temporaryFolder.newFolder("exist" + i).toPath().normalize().toAbsolutePath();
// load config from classpath and override data and journal dir
final Configuration configuration = new Configuration("conf.xml");
configuration.setProperty(BrokerPool.PROPERTY_DATA_DIR, dataDir);
configuration.setProperty(Journal.PROPERTY_RECOVERY_JOURNAL_DIR, dataDir);
BrokerPool.configure("instance" + i, 0, 1, configuration);
shutdownTasks.add(executorService.submit(new BrokerPoolShutdownTask(acquiredLatch, shutdownLatch)));
}
// wait for all shutdown threads to be acquired
acquiredLatch.await();
shutdownLatch.countDown();
executorService.shutdown();
assertTrue(executorService.awaitTermination(8, TimeUnit.SECONDS));
for (final Future<Exception> shutdownTask : shutdownTasks) {
assertNull(shutdownTask.get());
}
}
use of org.exist.EXistException in project exist by eXist-db.
the class PropertyGet method getPropertyString.
protected static StringBuilder getPropertyString(Variable variable, XQueryContext context) {
Sequence value = variable.getValue();
Database db = context.getDatabase();
try (final DBBroker broker = db.getBroker()) {
Serializer serializer = broker.getSerializer();
serializer.reset();
try {
StringBuilder property = new StringBuilder();
if (value.hasOne()) {
String strVal = getPropertyValue(value.itemAt(0), serializer);
String type = Type.subTypeOf(value.getItemType(), Type.NODE) ? "node" : Type.getTypeName(value.getItemType());
property.append("<property name=\"");
property.append(variable.getQName().toString());
property.append("\" fullname=\"");
property.append(variable.getQName().toString());
property.append("\" type=\"");
property.append(type);
property.append("\" size=\"");
property.append(strVal.length());
property.append("\" encoding=\"none\">");
property.append(strVal);
property.append("</property>");
} else {
property.append("<property name=\"");
property.append(variable.getQName().toString());
property.append("\" fullname=\"");
property.append(variable.getQName().toString());
property.append("\" type=\"array\" children=\"true\" numchildren=\"");
property.append(value.getItemCount());
property.append("\">");
int idx = 0;
for (SequenceIterator si = value.iterate(); si.hasNext(); idx++) {
Item item = si.nextItem();
String strVal = getPropertyValue(item, serializer);
String type = Type.subTypeOf(value.getItemType(), Type.NODE) ? "xs:string" : Type.getTypeName(value.getItemType());
property.append("<property name=\"");
property.append(idx);
property.append("\" type=\"");
property.append(type);
property.append("\" size=\"");
property.append(strVal.length());
property.append("\" encoding=\"none\">");
property.append(strVal);
property.append("</property>");
}
property.append("</property>");
}
return property;
} catch (SAXException e) {
e.printStackTrace();
} catch (XPathException e) {
e.printStackTrace();
}
} catch (EXistException e) {
e.printStackTrace();
}
return null;
}
Aggregations