io.milton.http.acl.PrincipalPropertySearchReport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of milton-server-ent Show documentation
Show all versions of milton-server-ent Show documentation
Milton Enterprise: Supports DAV level 2 and above, including Caldav and Carddav. Available on AGPL or
commercial licenses
/*
* Copyright 2012 McEvoy Software Ltd.
*
*/
package io.milton.http.acl;
import io.milton.http.caldav.CalDavProtocol;
import io.milton.http.caldav.CalendarQueryReport;
import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.NotAuthorizedException;
import io.milton.http.report.Report;
import io.milton.http.report.ReportUtils;
import io.milton.http.webdav.PropFindPropertyBuilder;
import io.milton.http.webdav.PropFindResponse;
import io.milton.http.webdav.PropFindXmlGenerator;
import io.milton.http.webdav.PropertiesRequest;
import io.milton.http.webdav.WebDavProtocol;
import io.milton.principal.DiscretePrincipal;
import io.milton.principal.PrincipalSearchCriteria;
import io.milton.principal.PrincipalSearchCriteria.SearchItem;
import io.milton.principal.PrincipalSearchService;
import io.milton.resource.PropFindableResource;
import io.milton.resource.Resource;
import java.util.*;
import javax.xml.namespace.QName;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.filter.ElementFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The report can be used to search principals for matching properties and
* return specified properties for the matching principal resources. To search
* for an address book owned by a user named "Laurie", the REPORT request body
* would look like this:
*
<?xml version="1.0" encoding="utf-8" ?>
<D:principal-property-search xmlns:D="DAV:">
<D:property-search>
<D:prop>
<D:displayname/>
</D:prop>
<D:match>Laurie</D:match>
</D:property-search>
<D:prop>
<C:addressbook-home-set xmlns:C="urn:ietf:params:xml:ns:carddav"/>
<D:displayname/>
</D:prop>
</D:principal-property-search>
*
* The server performs a case-sensitive or caseless search for a matching string
* subset of "Laurie" within the DAV:displayname property. Thus, the server
* might return "Laurie Dusseault", "Laurier Desruisseaux", or "Wilfrid Laurier"
* all as matching DAV:displayname values, and the address books for each of
* these.
*
* @author nabil.shams
*/
public class PrincipalPropertySearchReport implements Report {
private static final Logger log = LoggerFactory.getLogger(CalendarQueryReport.class);
private final PropFindPropertyBuilder propertyBuilder;
private final PropFindXmlGenerator xmlGenerator;
private final PrincipalSearchService principalSearchService;
private final Namespace NS_DAV = Namespace.getNamespace(WebDavProtocol.NS_DAV.getPrefix(), WebDavProtocol.NS_DAV.getName());
private final Namespace NS_CAL = Namespace.getNamespace("C", CalDavProtocol.CALDAV_NS);
public PrincipalPropertySearchReport(PropFindPropertyBuilder propertyBuilder, PropFindXmlGenerator xmlGenerator, PrincipalSearchService principalSearchService) {
this.propertyBuilder = propertyBuilder;
this.xmlGenerator = xmlGenerator;
this.principalSearchService = principalSearchService;
}
@Override
public String getName() {
return "principal-property-search";
}
@Override
public String process(String host, String path, Resource r, Document doc) throws BadRequestException, NotAuthorizedException {
log.debug("process");
// The requested properties
Set props = getProps(doc);
PropertiesRequest parseResult = PropertiesRequest.toProperties(props);
// Generate the response
List respProps = new ArrayList<>();
PrincipalSearchCriteria crit = new PrincipalSearchCriteria();
List searchTerms = new ArrayList<>();
for (Element el : ReportUtils.findAll(doc.getRootElement(), "property-search", NS_DAV)) {
String field = null;
Element elProp = ReportUtils.find(el, "prop", NS_DAV);
Iterator propIter = elProp.getContent(new ElementFilter()).iterator();
if(propIter.hasNext()) {
Element elPropChild = (Element) propIter.next();
QName qname = new QName(elPropChild.getNamespaceURI(), elPropChild.getName());
field = qname.toString();
if(propIter.hasNext()) {
log.warn("Multiple children of property-search/prop element not supported");
}
} else {
log.warn("property-search/prop element has no children");
}
Element elMatch = ReportUtils.find(el, "match", NS_DAV);
PrincipalSearchCriteria.MatchType matchType = PrincipalSearchCriteria.MatchType.CONTAINS;
String matchAttr = elMatch.getAttributeValue("match-type");
if(matchAttr != null) {
matchType = PrincipalSearchCriteria.MatchType.fromCode(matchAttr);
}
String matchVal = elMatch.getText();
SearchItem item = new PrincipalSearchCriteria.SearchItem();
item.setField(field);
item.setMatchType(matchType);
item.setValue(matchVal);
searchTerms.add(item);
}
crit.setSearchItems(searchTerms);
crit.setCuType(null); // TODO
String typeAttr = doc.getRootElement().getAttributeValue("test");
crit.setTest(PrincipalSearchCriteria.TestType.fromCode(typeAttr));
List foundResources = principalSearchService.search(crit, r);
if (foundResources != null) {
log.info("foundResources: " + foundResources.size());
} else {
log.info("foundResources: null");
}
for (DiscretePrincipal dp : foundResources) {
String href = dp.getPrincipalURL();
List resps = new ArrayList<>();
if (dp instanceof PropFindableResource) {
PropFindableResource pfr = (PropFindableResource) dp;
propertyBuilder.processResource(resps, pfr, parseResult, href, 0, 0, href);
}
respProps.addAll(resps);
}
String xml = xmlGenerator.generate(respProps);
log.debug(xml);
return xml;
}
private Set getProps(Document doc) {
Element elProp = doc.getRootElement().getChild("prop", NS_DAV);
if (elProp == null) {
throw new RuntimeException("No prop element");
}
Set set = new HashSet<>();
for (Object o : elProp.getChildren()) {
if (o instanceof Element) {
Element el = (Element) o;
String local = el.getName();
String ns = el.getNamespaceURI();
set.add(new QName(ns, local, el.getNamespacePrefix()));
}
}
return set;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy