1
0
mirror of https://github.com/moparisthebest/davmail synced 2024-11-15 05:45:12 -05:00

Carddav: use new ExchangePropPatchMethod in full contact create/update

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1261 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-07-24 10:54:27 +00:00
parent 5ad16b3b65
commit 3418daed65
4 changed files with 89 additions and 38 deletions

View File

@ -596,12 +596,12 @@ public class DavExchangeSession extends ExchangeSession {
super(folderPath, itemName, properties, etag, noneMatch); super(folderPath, itemName, properties, etag, noneMatch);
} }
protected List<DavConstants> buildProperties() { protected Set<PropertyValue> buildProperties() {
ArrayList<DavConstants> list = new ArrayList<DavConstants>(); Set<PropertyValue> list = new HashSet<PropertyValue>();
for (Map.Entry<String, String> entry : entrySet()) { for (Map.Entry<String, String> entry : entrySet()) {
String key = entry.getKey(); String key = entry.getKey();
if (!"photo".equals(key)) { if (!"photo".equals(key)) {
list.add(Field.createDavProperty(key, entry.getValue())); list.add(Field.createPropertyValue(key, entry.getValue()));
} }
} }
@ -616,7 +616,7 @@ public class DavExchangeSession extends ExchangeSession {
*/ */
public ItemResult createOrUpdate() throws IOException { public ItemResult createOrUpdate() throws IOException {
int status = 0; int status = 0;
PropPatchMethod propPatchMethod = new PropPatchMethod(URIUtil.encodePath(getHref()), buildProperties()) { ExchangePropPatchMethod propPatchMethod = new ExchangePropPatchMethod(URIUtil.encodePath(getHref()), buildProperties()) {
@Override @Override
protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) { protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) {
// ignore response body, sometimes invalid with exchange mapi properties // ignore response body, sometimes invalid with exchange mapi properties
@ -697,7 +697,7 @@ public class DavExchangeSession extends ExchangeSession {
// update haspicture flag to boolean property // update haspicture flag to boolean property
DavPropertyName hasPicturePropertyName = Field.getPropertyName("haspicture"); DavPropertyName hasPicturePropertyName = Field.getPropertyName("haspicture");
Set<PropertyValue> propertyValues = new HashSet<PropertyValue>(); Set<PropertyValue> propertyValues = new HashSet<PropertyValue>();
propertyValues.add(new PropertyValue(hasPicturePropertyName.getNamespace(),hasPicturePropertyName.getName(),"1", PropertyType.Boolean)); propertyValues.add(new PropertyValue(hasPicturePropertyName.getNamespace().getURI(),hasPicturePropertyName.getName(),"1", PropertyType.Boolean));
ExchangePropPatchMethod exchangePropPatchMethod = new ExchangePropPatchMethod(URIUtil.encodePath(getHref()), propertyValues); ExchangePropPatchMethod exchangePropPatchMethod = new ExchangePropPatchMethod(URIUtil.encodePath(getHref()), propertyValues);
try { try {
status = httpClient.executeMethod(exchangePropPatchMethod); status = httpClient.executeMethod(exchangePropPatchMethod);

View File

@ -18,7 +18,6 @@
*/ */
package davmail.exchange.dav; package davmail.exchange.dav;
import davmail.util.StringUtil;
import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.RequestEntity;
@ -41,7 +40,7 @@ import java.util.*;
public class ExchangePropPatchMethod extends EntityEnclosingMethod { public class ExchangePropPatchMethod extends EntityEnclosingMethod {
protected static final Logger logger = Logger.getLogger(ExchangePropPatchMethod.class); protected static final Logger logger = Logger.getLogger(ExchangePropPatchMethod.class);
static final Namespace TYPE_NAMESPACE = Namespace.getNamespace("urn:schemas-microsoft-com:datatypes"); static final String TYPE_NAMESPACE = "urn:schemas-microsoft-com:datatypes";
final Set<PropertyValue> propertyValues; final Set<PropertyValue> propertyValues;
/** /**
@ -84,7 +83,7 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
try { try {
// build namespace map // build namespace map
int currentChar = 'e'; int currentChar = 'e';
final Map<Namespace, Integer> nameSpaceMap = new HashMap<Namespace, Integer>(); final Map<String, Integer> nameSpaceMap = new HashMap<String, Integer>();
final Set<PropertyValue> setPropertyValues = new HashSet<PropertyValue>(); final Set<PropertyValue> setPropertyValues = new HashSet<PropertyValue>();
final Set<PropertyValue> deletePropertyValues = new HashSet<PropertyValue>(); final Set<PropertyValue> deletePropertyValues = new HashSet<PropertyValue>();
for (PropertyValue propertyValue : propertyValues) { for (PropertyValue propertyValue : propertyValues) {
@ -93,11 +92,11 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
nameSpaceMap.put(TYPE_NAMESPACE, currentChar++); nameSpaceMap.put(TYPE_NAMESPACE, currentChar++);
} }
// property namespace // property namespace
Namespace namespace = propertyValue.getNamespace(); String namespaceUri = propertyValue.getNamespaceUri();
if (!nameSpaceMap.containsKey(namespace)) { if (!nameSpaceMap.containsKey(namespaceUri)) {
nameSpaceMap.put(namespace, currentChar++); nameSpaceMap.put(namespaceUri, currentChar++);
} }
if (propertyValue.getValue() == null) { if (propertyValue.getXmlEncodedValue() == null) {
deletePropertyValues.add(propertyValue); deletePropertyValues.add(propertyValue);
} else { } else {
setPropertyValues.add(propertyValue); setPropertyValues.add(propertyValue);
@ -106,11 +105,11 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8"); OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8");
writer.write("<D:propertyupdate xmlns:D=\"DAV:\""); writer.write("<D:propertyupdate xmlns:D=\"DAV:\"");
for (Map.Entry<Namespace, Integer> mapEntry : nameSpaceMap.entrySet()) { for (Map.Entry<String, Integer> mapEntry : nameSpaceMap.entrySet()) {
writer.write(" xmlns:"); writer.write(" xmlns:");
writer.write((char) mapEntry.getValue().intValue()); writer.write((char) mapEntry.getValue().intValue());
writer.write("=\""); writer.write("=\"");
writer.write(mapEntry.getKey().getURI()); writer.write(mapEntry.getKey());
writer.write("\""); writer.write("\"");
} }
writer.write(">"); writer.write(">");
@ -118,7 +117,7 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
writer.write("<D:set><D:prop>"); writer.write("<D:set><D:prop>");
for (PropertyValue propertyValue : setPropertyValues) { for (PropertyValue propertyValue : setPropertyValues) {
PropertyType propertyType = propertyValue.getType(); PropertyType propertyType = propertyValue.getType();
char nameSpaceChar = (char) nameSpaceMap.get(propertyValue.getNamespace()).intValue(); char nameSpaceChar = (char) nameSpaceMap.get(propertyValue.getNamespaceUri()).intValue();
writer.write('<'); writer.write('<');
writer.write(nameSpaceChar); writer.write(nameSpaceChar);
writer.write(':'); writer.write(':');
@ -131,7 +130,7 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
writer.write("\""); writer.write("\"");
} }
writer.write('>'); writer.write('>');
writer.write(StringUtil.xmlEncode(propertyValue.getValue())); writer.write(propertyValue.getXmlEncodedValue());
writer.write("</"); writer.write("</");
writer.write(nameSpaceChar); writer.write(nameSpaceChar);
writer.write(':'); writer.write(':');
@ -143,7 +142,7 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
if (!deletePropertyValues.isEmpty()) { if (!deletePropertyValues.isEmpty()) {
writer.write("<D:remove><D:prop>"); writer.write("<D:remove><D:prop>");
for (PropertyValue propertyValue : deletePropertyValues) { for (PropertyValue propertyValue : deletePropertyValues) {
char nameSpaceChar = (char) nameSpaceMap.get(propertyValue.getNamespace()).intValue(); char nameSpaceChar = (char) nameSpaceMap.get(propertyValue.getNamespaceUri()).intValue();
writer.write('<'); writer.write('<');
writer.write(nameSpaceChar); writer.write(nameSpaceChar);
writer.write(':'); writer.write(':');
@ -220,18 +219,41 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
protected void handleResponse(XMLStreamReader reader) throws XMLStreamException { protected void handleResponse(XMLStreamReader reader) throws XMLStreamException {
MultiStatusResponse multiStatusResponse = null; MultiStatusResponse multiStatusResponse = null;
int currentStatus = 0; int status = 0;
String href = null;
while (reader.hasNext() && !isEndTag(reader, "response")) { while (reader.hasNext() && !isEndTag(reader, "response")) {
int event = reader.next(); int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) { if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName(); String tagLocalName = reader.getLocalName();
if ("href".equals(tagLocalName)) { if ("href".equals(tagLocalName)) {
multiStatusResponse = new MultiStatusResponse(reader.getElementText(), ""); href = reader.getElementText();
} else if ("status".equals(tagLocalName)) { } else if ("status".equals(tagLocalName)) {
if ("HTTP/1.1 200 OK".equals(reader.getElementText())) { String responseStatus = reader.getElementText();
currentStatus = HttpStatus.SC_OK; if ("HTTP/1.1 200 OK".equals(responseStatus)) {
status = HttpStatus.SC_OK;
} else if ("HTTP/1.1 201 Created".equals(responseStatus)) {
status = HttpStatus.SC_CREATED;
} }
} else if ("prop".equals(tagLocalName) && currentStatus == HttpStatus.SC_OK) { multiStatusResponse = new MultiStatusResponse(href, status);
} else if ("propstat".equals(tagLocalName)) {
handlePropstat(reader, multiStatusResponse);
}
}
}
}
protected void handlePropstat(XMLStreamReader reader, MultiStatusResponse multiStatusResponse) throws XMLStreamException {
int propstatStatus = 0;
while (reader.hasNext() && !isEndTag(reader, "propstat")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
if ("status".equals(tagLocalName)) {
if ("HTTP/1.1 200 OK".equals(reader.getElementText())) {
propstatStatus = HttpStatus.SC_OK;
}
} else if ("prop".equals(tagLocalName) && propstatStatus == HttpStatus.SC_OK) {
handleProperty(reader, multiStatusResponse); handleProperty(reader, multiStatusResponse);
} }
} }
@ -239,6 +261,7 @@ public class ExchangePropPatchMethod extends EntityEnclosingMethod {
} }
protected void handleProperty(XMLStreamReader reader, MultiStatusResponse multiStatusResponse) throws XMLStreamException { protected void handleProperty(XMLStreamReader reader, MultiStatusResponse multiStatusResponse) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "prop")) { while (reader.hasNext() && !isEndTag(reader, "prop")) {
try { try {

View File

@ -18,6 +18,7 @@
*/ */
package davmail.exchange.dav; package davmail.exchange.dav;
import davmail.util.StringUtil;
import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavPropertyName;
import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
@ -477,6 +478,36 @@ public class Field {
} }
} }
public static PropertyValue createPropertyValue(String alias, String value) {
Field field = Field.get(alias);
String encodedValue = null;
DavPropertyName davPropertyName = field.davPropertyName;
if (value == null) {
// return DavPropertyName to remove property
return new PropertyValue(davPropertyName.getNamespace().getURI(), davPropertyName.getName());
} else if (field.isMultivalued) {
StringBuilder buffer = new StringBuilder();
// multivalued field, split values separated by \n
String[] values = value.split("\n");
for (final String singleValue : values) {
buffer.append("<v xmlns=\"xml:\">");
buffer.append(StringUtil.xmlEncode(singleValue));
buffer.append("</v>");
}
return new PropertyValue(davPropertyName.getNamespace().getURI(), davPropertyName.getName(), buffer.toString());
} else if (field.isBooleanValue) {
if ("true".equals(value)) {
return new PropertyValue(davPropertyName.getNamespace().getURI(), davPropertyName.getName(), "1");
} else if ("false".equals(value)) {
return new PropertyValue(davPropertyName.getNamespace().getURI(), davPropertyName.getName(), "0");
} else {
throw new RuntimeException("Invalid value for " + field.alias + ": " + value);
}
} else {
return new PropertyValue(davPropertyName.getNamespace().getURI(), davPropertyName.getName(), StringUtil.xmlEncode(value));
}
}
/** /**
* SEARCH request property name for alias * SEARCH request property name for alias
* *

View File

@ -18,39 +18,36 @@
*/ */
package davmail.exchange.dav; package davmail.exchange.dav;
import org.apache.jackrabbit.webdav.xml.Namespace;
/** /**
* Property value. * Property value.
*/ */
public class PropertyValue { public class PropertyValue {
protected Namespace namespace; protected String namespaceUri;
protected String name; protected String name;
protected String value; protected String xmlEncodedValue;
protected PropertyType type; protected PropertyType type;
public PropertyValue(Namespace namespace, String name) { public PropertyValue(String namespaceUri, String name) {
this(namespace, name, null, null); this(namespaceUri, name, null, null);
} }
public PropertyValue(Namespace namespace, String name, String value) { public PropertyValue(String namespaceUri, String name, String xmlEncodedValue) {
this(namespace, name, value, null); this(namespaceUri, name, xmlEncodedValue, null);
} }
public PropertyValue(Namespace namespace, String name, String value, PropertyType type) { public PropertyValue(String namespaceUri, String name, String xmlEncodedValue, PropertyType type) {
this.namespace = namespace; this.namespaceUri = namespaceUri;
this.name = name; this.name = name;
this.value = value; this.xmlEncodedValue = xmlEncodedValue;
this.type = type; this.type = type;
} }
public Namespace getNamespace() { public String getNamespaceUri() {
return namespace; return namespaceUri;
} }
public String getValue() { public String getXmlEncodedValue() {
return value; return xmlEncodedValue;
} }
public PropertyType getType() { public PropertyType getType() {