1 package com.android.hotspot2.pps; 2 3 import com.android.hotspot2.Utils; 4 5 import java.util.ArrayList; 6 import java.util.Collections; 7 import java.util.HashMap; 8 import java.util.Iterator; 9 import java.util.List; 10 import java.util.Map; 11 12 public 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 Label(Match match)22 private Label(Match match) { 23 mMatch = match; 24 mSubDomains = match == Match.None ? new HashMap<String, Label>() : null; 25 } 26 addDomain(Iterator<String> labels, Match match)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 getSubLabel(String labelString)38 private Label getSubLabel(String labelString) { 39 return mSubDomains.get(labelString); 40 } 41 getMatch()42 public Match getMatch() { 43 return mMatch; 44 } 45 toString(StringBuilder sb)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 toString()60 public String toString() { 61 StringBuilder sb = new StringBuilder(); 62 toString(sb); 63 return sb.toString(); 64 } 65 } 66 DomainMatcher(List<String> primary, List<List<String>> secondary)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 * 80 * @param domain Domain to be checked. 81 * @return None if domain is not a sub-domain, Primary if it matched one of the primary domains 82 * or Secondary if it matched on of the secondary domains. 83 */ isSubDomain(List<String> domain)84 public Match isSubDomain(List<String> domain) { 85 86 Label label = mRoot; 87 for (String labelString : domain) { 88 label = label.getSubLabel(labelString); 89 if (label == null) { 90 return Match.None; 91 } else if (label.getMatch() != Match.None) { 92 return label.getMatch(); 93 } 94 } 95 return Match.None; // Domain is a super domain 96 } 97 arg2SubdomainOfArg1(List<String> arg1, List<String> arg2)98 public static boolean arg2SubdomainOfArg1(List<String> arg1, List<String> arg2) { 99 if (arg2.size() < arg1.size()) { 100 return false; 101 } 102 103 Iterator<String> l1 = arg1.iterator(); 104 Iterator<String> l2 = arg2.iterator(); 105 106 while (l1.hasNext()) { 107 if (!l1.next().equals(l2.next())) { 108 return false; 109 } 110 } 111 return true; 112 } 113 114 @Override toString()115 public String toString() { 116 return "Domain matcher " + mRoot; 117 } 118 119 private static final String[] TestDomains = { 120 "garbage.apple.com", 121 "apple.com", 122 "com", 123 "jan.android.google.com.", 124 "jan.android.google.com", 125 "android.google.com", 126 "google.com", 127 "jan.android.google.net.", 128 "jan.android.google.net", 129 "android.google.net", 130 "google.net", 131 "net.", 132 "." 133 }; 134 main(String[] args)135 public static void main(String[] args) { 136 DomainMatcher dm1 = new DomainMatcher(Utils.splitDomain("android.google.com"), 137 Collections.<List<String>>emptyList()); 138 for (String domain : TestDomains) { 139 System.out.println(domain + ": " + dm1.isSubDomain(Utils.splitDomain(domain))); 140 } 141 List<List<String>> secondaries = new ArrayList<List<String>>(); 142 secondaries.add(Utils.splitDomain("apple.com")); 143 secondaries.add(Utils.splitDomain("net")); 144 DomainMatcher dm2 = new DomainMatcher(Utils.splitDomain("android.google.com"), secondaries); 145 for (String domain : TestDomains) { 146 System.out.println(domain + ": " + dm2.isSubDomain(Utils.splitDomain(domain))); 147 } 148 } 149 } 150