io.milton.http.webdav.PropertySourcePatchSetter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of milton-server-ce Show documentation
Show all versions of milton-server-ce Show documentation
Milton Community Edition: Supports DAV level 1 and is available on Apache2 license
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.milton.http.webdav;
import io.milton.http.Response;
import io.milton.http.Response.Status;
import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.NotAuthorizedException;
import io.milton.http.values.ValueAndType;
import io.milton.http.values.ValueWriters;
import io.milton.http.webdav.PropFindResponse.NameAndError;
import io.milton.property.PropertySource;
import io.milton.property.PropertySource.PropertyMetaData;
import io.milton.property.PropertySource.PropertySetException;
import io.milton.resource.Resource;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author brad
*/
public class PropertySourcePatchSetter implements PropPatchSetter {
private static final Logger log = LoggerFactory.getLogger(PropertySourcePatchSetter.class);
private final List propertySources;
private final ValueWriters valueWriters;
public PropertySourcePatchSetter(List propertySources, ValueWriters valueWriters) {
this.propertySources = propertySources;
this.valueWriters = valueWriters;
}
public PropertySourcePatchSetter(List propertySources) {
this.propertySources = propertySources;
this.valueWriters = new ValueWriters();
}
/**
* This returns true for all resources, but it actually depends on the
* configured property sources.
*
* If no property sources support a given resource, a proppatch attempt
* will return 404's for all properties
*
* @param r
* @return
*/
@Override
public boolean supports(Resource r) {
return true;
}
@Override
public PropFindResponse setProperties(String href, PropPatchParseResult parseResult, Resource r) throws NotAuthorizedException, BadRequestException {
log.trace("setProperties: resource type: {}", r.getClass());
Map knownProps = new HashMap<>();
Map> errorProps = new EnumMap<>(Status.class);
for (Entry entry : parseResult.getFieldsToSet().entrySet()) {
QName name = entry.getKey();
boolean found = false;
for (PropertySource source : propertySources) {
PropertyMetaData meta = source.getPropertyMetaData(entry.getKey(), r);
if (meta != null && meta.isNotUnknownOrAlwaysWriteable()) {
found = true;
if (meta.isAlwaysWriteable()) {
Object val = parse(name, entry.getValue(), meta.getValueType());
try {
log.trace("setProperties: name: {} source: {}", name, source.getClass());
source.setProperty(name, val, r);
knownProps.put(name, new ValueAndType(null, meta.getValueType()));
break;
} catch (NotAuthorizedException e) {
log.warn("setProperties: NotAuthorised to write property: {}", name, e);
addErrorProp(errorProps, Response.Status.SC_UNAUTHORIZED, name, "Not authorised");
break;
} catch (PropertySetException ex) {
log.warn("setProperties: PropertySetException when writing property {}", name, ex);
addErrorProp(errorProps, ex.getStatus(), name, ex.getErrorNotes());
break;
}
} else {
log.warn("property is not writable in source: " + source.getClass());
addErrorProp(errorProps, Response.Status.SC_FORBIDDEN, name, "Property is read only");
break;
}
} else {
//log.debug( "not found in: " + source.getClass().getCanonicalName() );
}
}
if (!found) {
log.warn("property not found: " + entry.getKey() + " on resource: " + r.getClass());
addErrorProp(errorProps, Status.SC_NOT_FOUND, entry.getKey(), "Unknown property");
}
}
if (parseResult.getFieldsToRemove() != null) {
for (QName name : parseResult.getFieldsToRemove()) {
boolean found = false;
for (PropertySource source : propertySources) {
PropertyMetaData meta = source.getPropertyMetaData(name, r);
if (meta != null && !meta.isUnknown()) {
found = true;
if (meta.isWritable()) {
try {
log.trace("clearProperty");
source.clearProperty(name, r);
knownProps.put(name, new ValueAndType(null, meta.getValueType()));
break;
} catch (NotAuthorizedException e) {
addErrorProp(errorProps, Response.Status.SC_UNAUTHORIZED, name, "Not authorised");
break;
} catch (PropertySetException ex) {
addErrorProp(errorProps, ex.getStatus(), name, ex.getErrorNotes());
break;
}
} else {
log.warn("property is not writable in source: " + source.getClass());
addErrorProp(errorProps, Response.Status.SC_FORBIDDEN, name, "Property is read only");
break;
}
} else {
//log.debug( "not found in: " + source.getClass().getCanonicalName() );
}
}
if (!found) {
log.warn("property not found to remove: " + name);
addErrorProp(errorProps, Status.SC_NOT_FOUND, name, "Unknown property");
}
}
}
if (log.isDebugEnabled()) {
if (errorProps.size() > 0) {
log.debug("errorProps: " + errorProps.size() + " listing property sources:");
for (PropertySource s : propertySources) {
log.debug(" source: " + s.getClass().getCanonicalName());
}
}
}
if( r instanceof CommitableResource) {
log.trace("resource is commitable, call doCommit");
CommitableResource cr = (CommitableResource) r;
cr.doCommit(knownProps, errorProps);
} else {
log.trace("resource is not commitable");
}
return new PropFindResponse(href, knownProps, errorProps);
}
private void addErrorProp(Map> errorProps, Status stat, QName name, String err) {
List list = errorProps.computeIfAbsent(stat, k -> new ArrayList<>());
NameAndError ne = new NameAndError(name, err);
list.add(ne);
}
private Object parse(QName key, String value, Class valueType) {
return valueWriters.parse(key, valueType, value);
}
public interface CommitableResource extends Resource {
void doCommit(Map knownProps, Map> errorProps) throws BadRequestException, NotAuthorizedException ;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy