From ef23bf198d14bea183c0dabd5b4fcd0a5d07d738 Mon Sep 17 00:00:00 2001 From: Chiao Cheng Date: Wed, 20 Mar 2013 13:12:41 -0700 Subject: [PATCH] Allow leading slash in path argument for addURI() method. The original documentation for this class indicated a leading slash was possible but the code did not support it. Since then, the docs were changed to reflect what the code does. The purpose of this change is to allow the use of uri.getPath() as an argument. With this change, the following can be done matcher.addURI(ContactsContract.AUTHORITY, ContactsContract.CONTENT_FILTER_URI.getPath(), CONTACTS_FILTER) instead of matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER) Change-Id: I76a9e3133365be9fe7a8de86eae57f9eea1cd2a3 --- core/java/android/content/UriMatcher.java | 20 +++- .../src/android/net/UriMatcherTest.java | 111 +++++++++++------- 2 files changed, 86 insertions(+), 45 deletions(-) diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java index 841c8f43d42f0..1a8ea47ddfb50 100644 --- a/core/java/android/content/UriMatcher.java +++ b/core/java/android/content/UriMatcher.java @@ -69,6 +69,11 @@ For example: sURIMatcher.addURI("call_log", "calls/#", CALLS_ID); } +

Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, paths can start + with a leading slash. For example: +

+        sURIMatcher.addURI("contacts", "/people", PEOPLE);
+

Then when you need to match against a URI, call {@link #match}, providing the URL that you have been given. You can use the result to build a query, return a type, insert or delete a row, or whatever you need, without duplicating @@ -143,6 +148,9 @@ public class UriMatcher * matched. URI nodes may be exact match string, the token "*" * that matches any text, or the token "#" that matches only * numbers. + *

+ * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, + * this method will accept leading slash in the path. * * @param authority the authority to match * @param path the path to match. * may be used as a wild card for @@ -155,7 +163,17 @@ public class UriMatcher if (code < 0) { throw new IllegalArgumentException("code " + code + " is invalid: it must be positive"); } - String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null; + + String[] tokens = null; + if (path != null) { + String newPath = path; + // Strip leading slash if present. + if (path.length() > 0 && path.charAt(0) == '/') { + newPath = path.substring(1); + } + tokens = PATH_SPLIT_PATTERN.split(newPath); + } + int numTokens = tokens != null ? tokens.length : 0; UriMatcher node = this; for (int i = -1; i < numTokens; i++) { diff --git a/core/tests/coretests/src/android/net/UriMatcherTest.java b/core/tests/coretests/src/android/net/UriMatcherTest.java index 287214460b6af..a728d4fd58137 100644 --- a/core/tests/coretests/src/android/net/UriMatcherTest.java +++ b/core/tests/coretests/src/android/net/UriMatcherTest.java @@ -19,10 +19,11 @@ package android.net; import android.content.UriMatcher; import android.net.Uri; import android.test.suitebuilder.annotation.SmallTest; + import junit.framework.TestCase; -public class UriMatcherTest extends TestCase -{ +public class UriMatcherTest extends TestCase { + static final int ROOT = 0; static final int PEOPLE = 1; static final int PEOPLE_ID = 2; @@ -37,54 +38,76 @@ public class UriMatcherTest extends TestCase static final int CALLERID = 11; static final int CALLERID_TEXT = 12; static final int FILTERRECENT = 13; - + static final int ANOTHER_PATH_SEGMENT = 13; + @SmallTest public void testContentUris() { - check("content://asdf", UriMatcher.NO_MATCH); - check("content://people", PEOPLE); - check("content://people/1", PEOPLE_ID); - check("content://people/asdf", UriMatcher.NO_MATCH); - check("content://people/2/phones", PEOPLE_PHONES); - check("content://people/2/phones/3", PEOPLE_PHONES_ID); - check("content://people/2/phones/asdf", UriMatcher.NO_MATCH); - check("content://people/2/addresses", PEOPLE_ADDRESSES); - check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID); - check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH); - check("content://people/2/contact-methods", PEOPLE_CONTACTMETH); - check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID); - check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH); - check("content://calls", CALLS); - check("content://calls/1", CALLS_ID); - check("content://calls/asdf", UriMatcher.NO_MATCH); - check("content://caller-id", CALLERID); - check("content://caller-id/asdf", CALLERID_TEXT); - check("content://caller-id/1", CALLERID_TEXT); - check("content://filter-recent", FILTERRECENT); + UriMatcher matcher = new UriMatcher(ROOT); + matcher.addURI("people", null, PEOPLE); + matcher.addURI("people", "#", PEOPLE_ID); + matcher.addURI("people", "#/phones", PEOPLE_PHONES); + matcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID); + matcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID); + matcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES); + matcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID); + matcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH); + matcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID); + matcher.addURI("calls", null, CALLS); + matcher.addURI("calls", "#", CALLS_ID); + matcher.addURI("caller-id", null, CALLERID); + matcher.addURI("caller-id", "*", CALLERID_TEXT); + matcher.addURI("filter-recent", null, FILTERRECENT); + matcher.addURI("auth", "another/path/segment", ANOTHER_PATH_SEGMENT); + checkAll(matcher); } - private static final UriMatcher mURLMatcher = new UriMatcher(ROOT); - - static - { - mURLMatcher.addURI("people", null, PEOPLE); - mURLMatcher.addURI("people", "#", PEOPLE_ID); - mURLMatcher.addURI("people", "#/phones", PEOPLE_PHONES); - mURLMatcher.addURI("people", "#/phones/blah", PEOPLE_PHONES_ID); - mURLMatcher.addURI("people", "#/phones/#", PEOPLE_PHONES_ID); - mURLMatcher.addURI("people", "#/addresses", PEOPLE_ADDRESSES); - mURLMatcher.addURI("people", "#/addresses/#", PEOPLE_ADDRESSES_ID); - mURLMatcher.addURI("people", "#/contact-methods", PEOPLE_CONTACTMETH); - mURLMatcher.addURI("people", "#/contact-methods/#", PEOPLE_CONTACTMETH_ID); - mURLMatcher.addURI("calls", null, CALLS); - mURLMatcher.addURI("calls", "#", CALLS_ID); - mURLMatcher.addURI("caller-id", null, CALLERID); - mURLMatcher.addURI("caller-id", "*", CALLERID_TEXT); - mURLMatcher.addURI("filter-recent", null, FILTERRECENT); + @SmallTest + public void testContentUrisWithLeadingSlash() { + UriMatcher matcher = new UriMatcher(ROOT); + matcher.addURI("people", null, PEOPLE); + matcher.addURI("people", "/#", PEOPLE_ID); + matcher.addURI("people", "/#/phones", PEOPLE_PHONES); + matcher.addURI("people", "/#/phones/blah", PEOPLE_PHONES_ID); + matcher.addURI("people", "/#/phones/#", PEOPLE_PHONES_ID); + matcher.addURI("people", "/#/addresses", PEOPLE_ADDRESSES); + matcher.addURI("people", "/#/addresses/#", PEOPLE_ADDRESSES_ID); + matcher.addURI("people", "/#/contact-methods", PEOPLE_CONTACTMETH); + matcher.addURI("people", "/#/contact-methods/#", PEOPLE_CONTACTMETH_ID); + matcher.addURI("calls", null, CALLS); + matcher.addURI("calls", "/#", CALLS_ID); + matcher.addURI("caller-id", null, CALLERID); + matcher.addURI("caller-id", "/*", CALLERID_TEXT); + matcher.addURI("filter-recent", null, FILTERRECENT); + matcher.addURI("auth", "/another/path/segment", ANOTHER_PATH_SEGMENT); + checkAll(matcher); } - void check(String uri, int expected) - { - int result = mURLMatcher.match(Uri.parse(uri)); + private void checkAll(UriMatcher matcher) { + check("content://asdf", UriMatcher.NO_MATCH, matcher); + check("content://people", PEOPLE, matcher); + check("content://people/1", PEOPLE_ID, matcher); + check("content://people/asdf", UriMatcher.NO_MATCH, matcher); + check("content://people/2/phones", PEOPLE_PHONES, matcher); + check("content://people/2/phones/3", PEOPLE_PHONES_ID, matcher); + check("content://people/2/phones/asdf", UriMatcher.NO_MATCH, matcher); + check("content://people/2/addresses", PEOPLE_ADDRESSES, matcher); + check("content://people/2/addresses/3", PEOPLE_ADDRESSES_ID, matcher); + check("content://people/2/addresses/asdf", UriMatcher.NO_MATCH, matcher); + check("content://people/2/contact-methods", PEOPLE_CONTACTMETH, matcher); + check("content://people/2/contact-methods/3", PEOPLE_CONTACTMETH_ID, matcher); + check("content://people/2/contact-methods/asdf", UriMatcher.NO_MATCH, matcher); + check("content://calls", CALLS, matcher); + check("content://calls/1", CALLS_ID, matcher); + check("content://calls/asdf", UriMatcher.NO_MATCH, matcher); + check("content://caller-id", CALLERID, matcher); + check("content://caller-id/asdf", CALLERID_TEXT, matcher); + check("content://caller-id/1", CALLERID_TEXT, matcher); + check("content://filter-recent", FILTERRECENT, matcher); + check("content://auth/another/path/segment", ANOTHER_PATH_SEGMENT, matcher); + } + + private void check(String uri, int expected, UriMatcher matcher) { + int result = matcher.match(Uri.parse(uri)); if (result != expected) { String msg = "failed on " + uri; msg += " expected " + expected + " got " + result;