DomainMatcher.java revision 77f2b82a2e80af8da52c22d69a76def6d4209757
1package com.android.server.wifi.hotspot2.pps;
2
3import com.android.server.wifi.hotspot2.Utils;
4
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.List;
10import java.util.Map;
11
12public class DomainMatcher {
13
14    public enum Match {None, Primary, Secondary}
15
16    private final Label mRoot;
17
18    private static class Label {
19        private final Map<String, Label> mSubDomains;
20        private final Match mMatch;
21
22        private Label(Match match) {
23            mMatch = match;
24            mSubDomains = match == Match.None ? new HashMap<String, Label>() : null;
25        }
26
27        private void addDomain(Iterator<String> labels, Match match) {
28            String labelName = labels.next();
29            if (labels.hasNext()) {
30                Label subLabel = new Label(Match.None);
31                mSubDomains.put(labelName, subLabel);
32                subLabel.addDomain(labels, match);
33            } else {
34                mSubDomains.put(labelName, new Label(match));
35            }
36        }
37
38        private Label getSubLabel(String labelString) {
39            return mSubDomains.get(labelString);
40        }
41
42        public Match getMatch() {
43            return mMatch;
44        }
45
46        private void toString(StringBuilder sb) {
47            if (mSubDomains != null) {
48                sb.append(".{");
49                for (Map.Entry<String, Label> entry : mSubDomains.entrySet()) {
50                    sb.append(entry.getKey());
51                    entry.getValue().toString(sb);
52                }
53                sb.append('}');
54            } else {
55                sb.append('=').append(mMatch);
56            }
57        }
58
59        @Override
60        public String toString() {
61            StringBuilder sb = new StringBuilder();
62            toString(sb);
63            return sb.toString();
64        }
65    }
66
67    public DomainMatcher(List<String> primary, List<List<String>> secondary) {
68        mRoot = new Label(Match.None);
69        for (List<String> secondaryLabel : secondary) {
70            mRoot.addDomain(secondaryLabel.iterator(), Match.Secondary);
71        }
72        // Primary overwrites secondary.
73        mRoot.addDomain(primary.iterator(), Match.Primary);
74    }
75
76    /**
77     * Check if domain is either a the same or a sub-domain of any of the domains in the domain tree
78     * in this matcher, i.e. all or or a sub-set of the labels in domain matches a path in the tree.
79     * @param domain Domain to be checked.
80     * @return None if domain is not a sub-domain, Primary if it matched one of the primary domains
81     * or Secondary if it matched on of the secondary domains.
82     */
83    public Match isSubDomain(List<String> domain) {
84
85        Label label = mRoot;
86        for (String labelString : domain) {
87            label = label.getSubLabel(labelString);
88            if (label == null) {
89                return Match.None;
90            } else if (label.getMatch() != Match.None) {
91                return label.getMatch();
92            }
93        }
94        return Match.None;  // Domain is a super domain
95    }
96
97    public static boolean arg2SubdomainOfArg1(List<String> arg1, List<String> arg2) {
98        if (arg2.size() < arg1.size()) {
99            return false;
100        }
101
102        Iterator<String> l1 = arg1.listIterator(arg1.size());
103        Iterator<String> l2 = arg2.listIterator(arg2.size());
104
105        while(l1.hasNext()) {
106            if (!l1.next().equals(l2.next())) {
107                return false;
108            }
109        }
110        return true;
111    }
112
113    @Override
114    public String toString() {
115        return "Domain matcher " + mRoot;
116    }
117
118    private static final String[] TestDomains = {
119            "garbage.apple.com",
120            "apple.com",
121            "com",
122            "jan.android.google.com.",
123            "jan.android.google.com",
124            "android.google.com",
125            "google.com",
126            "jan.android.google.net.",
127            "jan.android.google.net",
128            "android.google.net",
129            "google.net",
130            "net.",
131            "."
132    };
133
134    public static void main(String[] args) {
135        DomainMatcher dm1 = new DomainMatcher(Utils.splitDomain("android.google.com"),
136                Collections.<List<String>>emptyList());
137        for (String domain : TestDomains) {
138            System.out.println(domain + ": " + dm1.isSubDomain(Utils.splitDomain(domain)));
139        }
140        List<List<String>> secondaries = new ArrayList<List<String>>();
141        secondaries.add(Utils.splitDomain("apple.com"));
142        secondaries.add(Utils.splitDomain("net"));
143        DomainMatcher dm2 = new DomainMatcher(Utils.splitDomain("android.google.com"), secondaries);
144        for (String domain : TestDomains) {
145            System.out.println(domain + ": " + dm2.isSubDomain(Utils.splitDomain(domain)));
146        }
147    }
148}
149