1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.protocol;
29
30 import java.util.HashSet;
31 import java.util.LinkedHashMap;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.Set;
35 import java.util.concurrent.locks.ReentrantLock;
36
37 import org.apache.hc.core5.annotation.Contract;
38 import org.apache.hc.core5.annotation.ThreadingBehavior;
39 import org.apache.hc.core5.util.Args;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @Contract(threading = ThreadingBehavior.SAFE)
60 public class UriPatternMatcher<T> implements LookupRegistry<T> {
61
62 private final Map<String, T> map;
63
64 private final ReentrantLock lock;
65
66 public UriPatternMatcher() {
67 super();
68 this.map = new LinkedHashMap<>();
69 this.lock = new ReentrantLock();
70 }
71
72
73
74
75
76
77
78
79
80 public Set<Entry<String, T>> entrySet() {
81 lock.lock();
82 try {
83 return new HashSet<>(map.entrySet());
84 } finally {
85 lock.unlock();
86 }
87 }
88
89
90
91
92
93
94
95
96
97 @Override
98 public void register(final String pattern, final T obj) {
99 lock.lock();
100 try {
101 Args.notNull(pattern, "URI request pattern");
102 this.map.put(pattern, obj);
103 } finally {
104 lock.unlock();
105 }
106 }
107
108
109
110
111
112
113
114 @Override
115 public void unregister(final String pattern) {
116 lock.lock();
117 try {
118 if (pattern == null) {
119 return;
120 }
121 this.map.remove(pattern);
122 } finally {
123 lock.unlock();
124 }
125 }
126
127
128
129
130
131
132
133
134 @Override
135 public T lookup(final String path) {
136 lock.lock();
137 try {
138 Args.notNull(path, "Request path");
139
140 T obj = this.map.get(path);
141 if (obj == null) {
142
143 String bestMatch = null;
144 for (final String pattern : this.map.keySet()) {
145 if (matchUriRequestPattern(pattern, path)) {
146
147 if (bestMatch == null || (bestMatch.length() < pattern.length())
148 || (bestMatch.length() == pattern.length() && pattern.endsWith("*"))) {
149 obj = this.map.get(pattern);
150 bestMatch = pattern;
151 }
152 }
153 }
154 }
155 return obj;
156 } finally {
157 lock.unlock();
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170 protected boolean matchUriRequestPattern(final String pattern, final String path) {
171 if (pattern.equals("*")) {
172 return true;
173 }
174 return (pattern.endsWith("*") && path.startsWith(pattern.substring(0, pattern.length() - 1)))
175 || (pattern.startsWith("*") && path.endsWith(pattern.substring(1)));
176 }
177
178 @Override
179 public String toString() {
180 return this.map.toString();
181 }
182
183 }