Commit b440bb0e authored by Ricki Hirner's avatar Ricki Hirner

Optimizations

parent eec3f71b
Pipeline #8896083 passed with stage
in 4 minutes and 12 seconds
......@@ -96,13 +96,13 @@ open class DavResource @JvmOverloads constructor(
val rqBody = if (xmlBody != null) RequestBody.create(MIME_XML, xmlBody) else null
var response: Response? = null
for (attempt in 0..MAX_REDIRECTS-1) {
for (attempt in 1..MAX_REDIRECTS) {
response = httpClient.newCall(Request.Builder()
.method("MKCOL", rqBody)
.url(location)
.build()).execute()
if (response.isRedirect)
processRedirection(response)
processRedirect(response)
else
break
}
......@@ -121,7 +121,7 @@ open class DavResource @JvmOverloads constructor(
@Throws(IOException::class, HttpException::class, DavException::class)
fun get(accept: String): ResponseBody {
var response: Response? = null
for (attempt in 0..MAX_REDIRECTS-1) {
for (attempt in 1..MAX_REDIRECTS) {
response = httpClient.newCall(Request.Builder()
.get()
.url(location)
......@@ -129,7 +129,7 @@ open class DavResource @JvmOverloads constructor(
.header("Accept-Encoding", "identity") // disable compression because it can change the ETag
.build()).execute()
if (response.isRedirect)
processRedirection(response)
processRedirect(response)
else
break
}
......@@ -143,9 +143,9 @@ open class DavResource @JvmOverloads constructor(
val body = response.body() ?: throw HttpException("GET without response body")
val mimeType = body.contentType()
if (mimeType != null)
body.contentType()?.let { mimeType ->
properties[GetContentType.NAME] = GetContentType(mimeType)
}
return body
}
......@@ -163,7 +163,7 @@ open class DavResource @JvmOverloads constructor(
fun put(body: RequestBody, ifMatchETag: String?, ifNoneMatch: Boolean): Boolean {
var redirected = false
var response: Response? = null
for (attempt in 0..MAX_REDIRECTS-1) {
for (attempt in 1..MAX_REDIRECTS) {
val builder = Request.Builder()
.put(body)
.url(location)
......@@ -177,7 +177,7 @@ open class DavResource @JvmOverloads constructor(
response = httpClient.newCall(builder.build()).execute()
if (response.isRedirect) {
processRedirection(response)
processRedirect(response)
redirected = true
} else
break
......@@ -202,7 +202,7 @@ open class DavResource @JvmOverloads constructor(
@Throws(IOException::class, HttpException::class)
fun delete(ifMatchETag: String?) {
var response: Response? = null
for (attempt in 0..MAX_REDIRECTS-1) {
for (attempt in 1..MAX_REDIRECTS) {
val builder = Request.Builder()
.delete()
.url(location)
......@@ -210,19 +210,19 @@ open class DavResource @JvmOverloads constructor(
builder.header("If-Match", QuotedStringUtils.asQuotedString(ifMatchETag))
response = httpClient.newCall(builder.build()).execute()
if (response.isRedirect) {
processRedirection(response)
} else
if (response.isRedirect)
processRedirect(response)
else
break
}
checkStatus(response!!, false)
if (response.code() == 207) {
if (response.code() == 207)
/* If an error occurs deleting a member resource (a resource other than
the resource identified in the Request-URI), then the response can be
a 207 (Multi-Status). […] (RFC 4918 9.6.1. DELETE for Collections) */
throw HttpException(response)
} else
else
response.body()?.close()
}
......@@ -258,14 +258,14 @@ open class DavResource @JvmOverloads constructor(
serializer.endDocument()
var response: Response? = null
for (attempt in 0..MAX_REDIRECTS-1) {
for (attempt in 1..MAX_REDIRECTS) {
response = httpClient.newCall(Request.Builder()
.url(location)
.method("PROPFIND", RequestBody.create(MIME_XML, writer.toString()))
.header("Depth", depth.toString())
.build()).execute()
if (response.isRedirect)
processRedirection(response)
processRedirect(response)
else
break
}
......@@ -273,9 +273,11 @@ open class DavResource @JvmOverloads constructor(
checkStatus(response!!, false)
assertMultiStatus(response)
if (depth > 0)
if (depth > 0) {
// collection listing requested, drop old member information
members.clear()
related.clear()
}
response.body()?.charStream()?.use { processMultiStatus(it) }
}
......@@ -347,9 +349,10 @@ open class DavResource @JvmOverloads constructor(
}
/**
* Sets the new [location] in case of a redirect. Closes the [response] body.
* @throws HttpException in case of an HTTP error
*/
protected fun processRedirection(response: Response) {
protected fun processRedirect(response: Response) {
try {
response.header("Location")?.let {
val target = location.resolve(it)
......
......@@ -135,13 +135,12 @@ class HttpUtils {
val name = m.group(1)
var value = m.group(2)
val len = value.length
if (value[0] == '"' && value[len - 1] == '"') {
if (value[0] == '"' && value[len - 1] == '"')
// quoted-string
value = value
.substring(1, len - 1)
.replace("\\\"", "\"")
}
params.put(name.toLowerCase(), value)
params[name.toLowerCase()] = value
} else
unnamedParams.add(authParam)
}
......
......@@ -21,6 +21,8 @@ interface Property {
super.equals(o)
}
override fun hashCode() = namespace.hashCode() xor name.hashCode()
override fun toString() = "$name($namespace)"
}
......
......@@ -20,6 +20,7 @@ class PropertyCollection {
operator fun get(name: Property.Name): Property? {
if (!properties.isInitialized())
return null
val nsProperties = properties.value[name.namespace] ?: return null
return nsProperties[name.name]
}
......@@ -27,6 +28,7 @@ class PropertyCollection {
fun getMap(): Map<Property.Name, Property?> {
if (!properties.isInitialized())
return mapOf()
val map = HashMap<Property.Name, Property?>()
for ((namespace, nsProperties) in properties.value) {
for ((name, property) in nsProperties)
......@@ -46,11 +48,17 @@ class PropertyCollection {
}
fun remove(name: Property.Name) {
if (!properties.isInitialized())
return
val nsProperties = properties.value[name.namespace]
nsProperties?.remove(name.name)
}
fun size(): Int {
if (!properties.isInitialized())
return 0
var size = 0
for (nsProperties in properties.value.values)
size += nsProperties.size
......@@ -85,6 +93,9 @@ class PropertyCollection {
}
fun nullAllValues() {
if (!properties.isInitialized())
return
for ((_, nsProperties) in properties.value) {
for (name in nsProperties.keys)
nsProperties.put(name, null)
......@@ -94,8 +105,7 @@ class PropertyCollection {
override fun toString(): String {
val s = LinkedList<String>()
val properties = getMap()
for ((name, value) in properties)
for ((name, value) in getMap())
s.add("$name: $value")
return "[" + TextUtils.join(", ", s) + "]"
}
......
......@@ -13,7 +13,7 @@ import java.util.*
object PropertyRegistry {
val factories = HashMap<String, HashMap<String, PropertyFactory>>()
val factories = mutableMapOf<String /*namespace*/, MutableMap<String /*name*/, PropertyFactory>>()
init {
Constants.log.info("Registering DAV property factories");
......@@ -28,18 +28,15 @@ object PropertyRegistry {
val name = factory.getName()
var nsFactories = factories[name.namespace]
if (nsFactories == null) {
nsFactories = HashMap<String, PropertyFactory>()
nsFactories = mutableMapOf<String, PropertyFactory>()
factories[name.namespace] = nsFactories
}
nsFactories[name.name] = factory;
nsFactories[name.name] = factory
}
fun create(name: Property.Name, parser: XmlPullParser): Property? {
val map = factories[name.namespace]
if (map != null) {
val factory = map[name.name]
if (factory != null)
return factory.create(parser)
factories[name.namespace]?.let { nsFactories ->
nsFactories[name.name]?.let { factory -> return factory.create(parser) }
}
return null
}
......
......@@ -11,6 +11,7 @@ package at.bitfire.dav4android;
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import org.xmlpull.v1.XmlPullParserFactory
import java.io.IOException
import java.util.logging.Level
class XmlUtils {
......@@ -39,6 +40,7 @@ class XmlUtils {
fun newSerializer() = factory.newSerializer()!!
@Throws(IOException::class)
fun readText(parser: XmlPullParser): String? {
var text: String? = null
......@@ -51,13 +53,14 @@ class XmlUtils {
text = parser.text
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse text property", e);
}
return text
}
@Throws(IOException::class)
fun readTextPropertyList(parser: XmlPullParser, name: Property.Name, list: MutableList<String>) {
try {
val depth = parser.depth
......@@ -69,7 +72,7 @@ class XmlUtils {
list.add(parser.nextText())
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse text property list", e)
}
}
......
......@@ -18,9 +18,7 @@ class ServiceUnavailableException: HttpException {
var retryAfter: Date? = null
constructor(message: String?): super(HttpURLConnection.HTTP_UNAVAILABLE, message) {
retryAfter = null
}
constructor(message: String?): super(HttpURLConnection.HTTP_UNAVAILABLE, message)
constructor(response: Response): super(response) {
// Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
......
......@@ -8,8 +8,4 @@
package at.bitfire.dav4android.exception
class UnsupportedDavException: DavException {
constructor(message: String?): super(message)
}
class UnsupportedDavException(message: String?) : DavException(message)
\ No newline at end of file
......@@ -24,7 +24,7 @@ data class CalendarColor(
@JvmField
val NAME = Property.Name(XmlUtils.NS_APPLE_ICAL, "calendar-color")
val PATTERN = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?")
val PATTERN = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?")!!
/**
* Converts a WebDAV color from one of these formats:
......
......@@ -13,6 +13,7 @@ import at.bitfire.dav4android.Property
import at.bitfire.dav4android.PropertyFactory
import at.bitfire.dav4android.XmlUtils
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import java.util.logging.Level
// see RFC 5397: WebDAV Current Principal Extension
......@@ -45,7 +46,7 @@ data class CurrentUserPrincipal(
href = parser.nextText()
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse <current-user-principal>", e);
}
......
......@@ -13,6 +13,7 @@ import at.bitfire.dav4android.Property
import at.bitfire.dav4android.PropertyFactory
import at.bitfire.dav4android.XmlUtils
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import java.util.logging.Level
data class CurrentUserPrivilegeSet(
......@@ -66,7 +67,7 @@ data class CurrentUserPrivilegeSet(
parsePrivilege()
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse <current-user-privilege-set>", e)
return null
}
......
......@@ -28,7 +28,6 @@ class GetETag: Property {
weak = "W/"
opaque-tag = quoted-string
*/
var tag: String? = rawETag
tag?.let {
// remove trailing "W/"
......
......@@ -15,8 +15,8 @@ import at.bitfire.dav4android.XmlUtils
import okhttp3.internal.http.HttpDate
import org.xmlpull.v1.XmlPullParser
class GetLastModified(
var lastModified: Long?
data class GetLastModified(
var lastModified: Long
): Property {
companion object {
......@@ -24,27 +24,22 @@ class GetLastModified(
val NAME = Property.Name(XmlUtils.NS_WEBDAV, "getlastmodified")
}
constructor(rawDate: String?)
: this(null as Long?)
{
if (rawDate != null) {
val date = HttpDate.parse(rawDate)
if (date != null)
lastModified = date.time
else
Constants.log.warning("Couldn't parse Last-Modified date")
} else
Constants.log.warning("Last-Modified without date")
}
class Factory: PropertyFactory {
override fun getName() = NAME
override fun create(parser: XmlPullParser) =
override fun create(parser: XmlPullParser): GetLastModified? {
// <!ELEMENT getlastmodified (#PCDATA) >
GetLastModified(XmlUtils.readText(parser))
XmlUtils.readText(parser)?.let { rawDate ->
val date = HttpDate.parse(rawDate)
if (date != null)
return GetLastModified(date.time)
else
Constants.log.warning("Couldn't parse Last-Modified date")
}
return null
}
}
......
......@@ -19,7 +19,7 @@ abstract class HrefListProperty: Property {
val hrefs = LinkedList<String>()
override fun toString() = "hrefs=[" + TextUtils.join(", ", hrefs) + "]"
override fun toString() = "href=[" + TextUtils.join(", ", hrefs) + "]"
abstract class Factory: PropertyFactory {
......
......@@ -14,6 +14,7 @@ import at.bitfire.dav4android.Property
import at.bitfire.dav4android.PropertyFactory
import at.bitfire.dav4android.XmlUtils
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import java.util.logging.Level
class ResourceType: Property {
......@@ -58,7 +59,7 @@ class ResourceType: Property {
}
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse <resourcetype>", e);
return null
}
......
......@@ -8,6 +8,7 @@
package at.bitfire.dav4android.property
import android.text.TextUtils
import at.bitfire.dav4android.Constants
import at.bitfire.dav4android.Property
import at.bitfire.dav4android.PropertyFactory
......@@ -26,6 +27,7 @@ class SupportedAddressData: Property {
val types = mutableSetOf<MediaType>()
fun hasVCard4() = types.any { "text/vcard; version=4.0".equals(it.toString(), true) }
override fun toString() = "[" + TextUtils.join(", ", types) + "]"
class Factory: PropertyFactory {
......
......@@ -62,7 +62,7 @@ data class SupportedCalendarComponentSet(
}
eventType = parser.next()
}
} catch(e: Exception) {
} catch(e: XmlPullParserException) {
Constants.log.log(Level.SEVERE, "Couldn't parse <supported-calendar-component-set>", e)
return null
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment