Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef23bf19 authored by Chiao Cheng's avatar Chiao Cheng
Browse files

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
parent e4c9ac2d
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -69,6 +69,11 @@ For example:
        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
    }
</pre>
<p>Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, paths can start
 with a leading slash.  For example:
<pre>
        sURIMatcher.addURI("contacts", "/people", PEOPLE);
</pre>
<p>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.
     * <p>
     * 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++) {
+66 −43
Original line number Diff line number Diff line
@@ -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);
    @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);
    }

    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);
    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);
    }

    void check(String uri, int expected)
    {
        int result = mURLMatcher.match(Uri.parse(uri));
    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;