use of org.apache.jackrabbit.webdav.property.PropEntry in project jackrabbit by apache.
the class DefaultItemCollection method alterProperties.
/**
* Loops over the given <code>List</code>s and alters the properties accordingly.
* Changes are persisted at the end according to the rules defined with
* the {@link AbstractItemResource#complete()} method.<p>
* Please note: since there is only a single property
* ({@link ItemResourceConstants#JCR_MIXINNODETYPES}
* that can be set or removed with PROPPATCH, this method either succeeds
* or throws an exception, even if this violates RFC 2518. Thus no property
* specific multistatus will be created in case of an error.
*
* @param changeList
* @return
* @throws DavException
*/
@Override
public MultiStatusResponse alterProperties(List<? extends PropEntry> changeList) throws DavException {
for (PropEntry propEntry : changeList) {
if (propEntry instanceof DavPropertyName) {
// use the internal remove method in order to prevent premature 'save'
DavPropertyName propName = (DavPropertyName) propEntry;
internalRemoveProperty(propName);
} else if (propEntry instanceof DavProperty) {
// use the internal set method in order to prevent premature 'save'
DavProperty<?> prop = (DavProperty<?>) propEntry;
internalSetProperty(prop);
} else {
throw new IllegalArgumentException("unknown object in change list: " + propEntry.getClass().getName());
}
}
// TODO: missing undo of successful set/remove if subsequent operation fails
// NOTE, that this is relevant with transactions only.
// success: save all changes together if no error occurred
complete();
return new MultiStatusResponse(getHref(), DavServletResponse.SC_OK);
}
use of org.apache.jackrabbit.webdav.property.PropEntry in project jackrabbit by apache.
the class WebdavRequestImpl method parsePropPatchRequest.
/**
* Parse the PROPPATCH request body.
*/
private void parsePropPatchRequest() throws DavException {
proppatchSet = new DavPropertySet();
proppatchList = new ArrayList<PropEntry>();
Document requestDocument = getRequestDocument();
if (requestDocument == null) {
throw new DavException(DavServletResponse.SC_BAD_REQUEST, "Invalid request body.");
}
Element root = requestDocument.getDocumentElement();
if (!DomUtil.matches(root, XML_PROPERTYUPDATE, NAMESPACE)) {
log.warn("PropPatch-Request has no <DAV:propertyupdate> tag.");
throw new DavException(DavServletResponse.SC_BAD_REQUEST, "PropPatch-Request has no <propertyupdate> tag.");
}
ElementIterator it = DomUtil.getChildren(root);
while (it.hasNext()) {
Element el = it.nextElement();
if (DomUtil.matches(el, XML_SET, NAMESPACE)) {
Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE);
if (propEl != null) {
ElementIterator properties = DomUtil.getChildren(propEl);
while (properties.hasNext()) {
DavProperty<?> davProp = DefaultDavProperty.createFromXml(properties.nextElement());
proppatchSet.add(davProp);
proppatchList.add(davProp);
}
}
} else if (DomUtil.matches(el, XML_REMOVE, NAMESPACE)) {
Element propEl = DomUtil.getChildElement(el, XML_PROP, NAMESPACE);
if (propEl != null) {
ElementIterator properties = DomUtil.getChildren(propEl);
while (properties.hasNext()) {
DavProperty<?> davProp = DefaultDavProperty.createFromXml(properties.nextElement());
proppatchSet.add(davProp);
proppatchList.add(davProp.getName());
}
}
} else {
log.debug("Unknown element in DAV:propertyupdate: " + el.getNodeName());
// unknown child elements are ignored
}
}
}
use of org.apache.jackrabbit.webdav.property.PropEntry in project jackrabbit by apache.
the class DavResourceImpl method alterProperties.
public MultiStatusResponse alterProperties(List<? extends PropEntry> changeList) throws DavException {
if (isLocked(this)) {
throw new DavException(DavServletResponse.SC_LOCKED);
}
if (!exists()) {
throw new DavException(DavServletResponse.SC_NOT_FOUND);
}
MultiStatusResponse msr = new MultiStatusResponse(getHref(), null);
try {
Map<? extends PropEntry, ?> failures = config.getPropertyManager().alterProperties(getPropertyImportContext(changeList), isCollection());
if (failures.isEmpty()) {
// save all changes together (reverted in case this fails)
node.save();
} else {
// set/remove of at least a single prop failed: undo modifications.
node.refresh(false);
}
/* loop over list of properties/names that were successfully altered
and them to the multistatus response respecting the result of the
complete action. in case of failure set the status to 'failed-dependency'
in order to indicate, that altering those names/properties would
have succeeded, if no other error occured.*/
for (PropEntry propEntry : changeList) {
int statusCode;
if (failures.containsKey(propEntry)) {
Object error = failures.get(propEntry);
statusCode = (error instanceof RepositoryException) ? new JcrDavException((RepositoryException) error).getErrorCode() : DavServletResponse.SC_INTERNAL_SERVER_ERROR;
} else {
statusCode = (failures.isEmpty()) ? DavServletResponse.SC_OK : DavServletResponse.SC_FAILED_DEPENDENCY;
}
if (propEntry instanceof DavProperty) {
msr.add(((DavProperty<?>) propEntry).getName(), statusCode);
} else {
msr.add((DavPropertyName) propEntry, statusCode);
}
}
return msr;
} catch (RepositoryException e) {
// revert any changes made so far an throw exception
try {
node.refresh(false);
} catch (RepositoryException re) {
// should not happen
}
throw new JcrDavException(e);
}
}
use of org.apache.jackrabbit.webdav.property.PropEntry in project jackrabbit by apache.
the class VersionControlledItemCollection method resolveMergeConflict.
/**
* Resolve one or multiple merge conflicts present on this resource. Please
* note that the 'setProperties' or 'removeProperties' set my contain additional
* resource properties, that need to be changed. Those properties are left
* untouched, whereas the {@link #AUTO_MERGE_SET DAV:auto-merge-set}, is
* removed from the list upon successful resolution of a merge conflict.<br>
* If the removeProperties or setProperties set do not contain the mentioned
* merge conflict resource properties or if the value of those properties do
* not allow for a resolution of an existing merge conflict, this method
* returns silently.
*
* @param changeList
* @throws org.apache.jackrabbit.webdav.DavException
* @see Node#doneMerge(Version)
* @see Node#cancelMerge(Version)
*/
private void resolveMergeConflict(List<? extends PropEntry> changeList) throws DavException {
if (!exists()) {
throw new DavException(DavServletResponse.SC_NOT_FOUND);
}
try {
Node n = (Node) item;
VersionManager vMgr = getVersionManager();
String path = item.getPath();
DavProperty<?> autoMergeSet = null;
DavProperty<?> predecessorSet = null;
/* find DAV:auto-merge-set entries. If none exists no attempt is made
to resolve merge conflict > return silently */
for (int i = 0; i < changeList.size(); i++) {
PropEntry propEntry = changeList.get(i);
// conflicts are resolved with 'cancel'
if (propEntry instanceof DavPropertyName && AUTO_MERGE_SET.equals(propEntry)) {
// retrieve the current jcr:mergeFailed property values
if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) {
throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts.");
}
Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues();
for (Value value : mergeFailed) {
vMgr.cancelMerge(path, (Version) getRepositorySession().getNodeByIdentifier(value.getString()));
}
// remove this entry from the changeList
changeList.remove(propEntry);
} else if (propEntry instanceof DavProperty) {
if (AUTO_MERGE_SET.equals(((DavProperty<?>) propEntry).getName())) {
autoMergeSet = (DavProperty<?>) propEntry;
} else if (PREDECESSOR_SET.equals(((DavProperty<?>) propEntry).getName())) {
predecessorSet = (DavProperty<?>) propEntry;
}
}
}
// resolved individually according to the DAV:predecessor-set property.
if (autoMergeSet != null) {
// retrieve the current jcr:mergeFailed property values
if (!n.hasProperty(JcrConstants.JCR_MERGEFAILED)) {
throw new DavException(DavServletResponse.SC_CONFLICT, "Attempt to resolve non-existing merge conflicts.");
}
List<String> mergeset = new HrefProperty(autoMergeSet).getHrefs();
List<String> predecL;
if (predecessorSet == null) {
predecL = Collections.emptyList();
} else {
predecL = new HrefProperty(predecessorSet).getHrefs();
}
Session session = getRepositorySession();
// loop over the mergeFailed values (versions) and test whether they are
// removed from the DAV:auto-merge-set thus indicating resolution.
Value[] mergeFailed = n.getProperty(JcrConstants.JCR_MERGEFAILED).getValues();
for (Value value : mergeFailed) {
// build version-href from each entry in the jcr:mergeFailed property
// in order to be able to compare to the entries in the HrefProperty.
Version version = (Version) session.getNodeByIdentifier(value.getString());
String href = getLocatorFromItem(version).getHref(true);
// thus indicating that this merge conflict needs to be resolved.
if (!mergeset.contains(href)) {
// must be called.
if (predecL.contains(href)) {
vMgr.doneMerge(path, version);
} else {
vMgr.cancelMerge(path, version);
}
}
}
// after successful resolution of merge-conflicts according to
// DAV:auto-merge-set and DAV:predecessor-set remove these entries
// from the changeList.
changeList.remove(autoMergeSet);
if (predecessorSet != null) {
changeList.remove(predecessorSet);
}
}
} catch (RepositoryException e) {
throw new JcrDavException(e);
}
}
use of org.apache.jackrabbit.webdav.property.PropEntry in project jackrabbit by apache.
the class DefaultHandler method importProperties.
public Map<? extends PropEntry, ?> importProperties(PropertyImportContext importContext, boolean isCollection) throws RepositoryException {
if (!canImport(importContext, isCollection)) {
throw new RepositoryException("PropertyHandler " + getName() + " failed import properties");
}
// loop over List and remember all properties and propertyNames
// that failed to be imported (set or remove).
Map<PropEntry, RepositoryException> failures = new HashMap<PropEntry, RepositoryException>();
List<? extends PropEntry> changeList = importContext.getChangeList();
// for collections the import-root is the target node where properties
// are altered. in contrast 'non-collections' are with the handler
// represented by 'file' nodes, that must have a jcr:content child
// node, which holds all properties except jcr:created.
// -> see canImport for the corresponding assertions
Node cn = (Node) importContext.getImportRoot();
if (!isCollection && cn.hasNode(JcrConstants.JCR_CONTENT)) {
cn = cn.getNode(JcrConstants.JCR_CONTENT);
}
if (changeList != null) {
for (PropEntry propEntry : changeList) {
try {
if (propEntry instanceof DavPropertyName) {
// remove
DavPropertyName propName = (DavPropertyName) propEntry;
removeJcrProperty(propName, cn);
} else if (propEntry instanceof DavProperty) {
// add or modify property
DavProperty<?> prop = (DavProperty<?>) propEntry;
setJcrProperty(prop, cn);
} else {
// ignore any other entry in the change list
log.error("unknown object in change list: " + propEntry.getClass().getName());
}
} catch (RepositoryException e) {
failures.put(propEntry, e);
}
}
}
if (failures.isEmpty()) {
setLastModified(cn, IOUtil.UNDEFINED_LENGTH);
}
return failures;
}
Aggregations