1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.util;
15
16 import java.util.BitSet;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.StringTokenizer;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 public class IPAddressMap<TYPE> extends HashMap<String, TYPE>
40 {
41 private final HashMap<String,IPAddrPattern> _patterns = new HashMap<String,IPAddrPattern>();
42
43
44
45
46 public IPAddressMap()
47 {
48 super(11);
49 }
50
51
52
53
54
55
56 public IPAddressMap(int capacity)
57 {
58 super (capacity);
59 }
60
61
62
63
64
65
66
67 @Override
68 public TYPE put(String addrSpec, TYPE object)
69 throws IllegalArgumentException
70 {
71 if (addrSpec == null || addrSpec.trim().length() == 0)
72 throw new IllegalArgumentException("Invalid IP address pattern: "+addrSpec);
73
74 String spec = addrSpec.trim();
75 if (_patterns.get(spec) == null)
76 _patterns.put(spec,new IPAddrPattern(spec));
77
78 return super.put(spec, object);
79 }
80
81
82
83
84
85
86
87 @Override
88 public TYPE get(Object key)
89 {
90 return super.get(key);
91 }
92
93
94
95
96
97
98
99
100
101 public TYPE match(String addr)
102 {
103 Map.Entry<String, TYPE> entry = getMatch(addr);
104 return entry==null ? null : entry.getValue();
105 }
106
107
108
109
110
111
112
113
114
115 public Map.Entry<String, TYPE> getMatch(String addr)
116 {
117 if (addr != null)
118 {
119 for(Map.Entry<String, TYPE> entry: super.entrySet())
120 {
121 if (_patterns.get(entry.getKey()).match(addr))
122 {
123 return entry;
124 }
125 }
126 }
127 return null;
128 }
129
130
131
132
133
134
135
136
137
138 public Object getLazyMatches(String addr)
139 {
140 if (addr == null)
141 return LazyList.getList(super.entrySet());
142
143 Object entries = null;
144 for(Map.Entry<String, TYPE> entry: super.entrySet())
145 {
146 if (_patterns.get(entry.getKey()).match(addr))
147 {
148 entries = LazyList.add(entries,entry);
149 }
150 }
151 return entries;
152 }
153
154
155
156
157
158
159
160
161 private static class IPAddrPattern
162 {
163 private final OctetPattern[] _octets = new OctetPattern[4];
164
165
166
167
168
169
170
171 public IPAddrPattern(String value)
172 throws IllegalArgumentException
173 {
174 if (value == null || value.trim().length() == 0)
175 throw new IllegalArgumentException("Invalid IP address pattern: "+value);
176
177 try
178 {
179 StringTokenizer parts = new StringTokenizer(value, ".");
180
181 String part;
182 for (int idx=0; idx<4; idx++)
183 {
184 part = parts.hasMoreTokens() ? parts.nextToken().trim() : "0-255";
185
186 int len = part.length();
187 if (len == 0 && parts.hasMoreTokens())
188 throw new IllegalArgumentException("Invalid IP address pattern: "+value);
189
190 _octets[idx] = new OctetPattern(len==0 ? "0-255" : part);
191 }
192 }
193 catch (IllegalArgumentException ex)
194 {
195 throw new IllegalArgumentException("Invalid IP address pattern: "+value, ex);
196 }
197 }
198
199
200
201
202
203
204
205
206
207
208 public boolean match(String value)
209 throws IllegalArgumentException
210 {
211 if (value == null || value.trim().length() == 0)
212 throw new IllegalArgumentException("Invalid IP address: "+value);
213
214 try
215 {
216 StringTokenizer parts = new StringTokenizer(value, ".");
217
218 boolean result = true;
219 for (int idx=0; idx<4; idx++)
220 {
221 if (!parts.hasMoreTokens())
222 throw new IllegalArgumentException("Invalid IP address: "+value);
223
224 if (!(result &= _octets[idx].match(parts.nextToken())))
225 break;
226 }
227 return result;
228 }
229 catch (IllegalArgumentException ex)
230 {
231 throw new IllegalArgumentException("Invalid IP address: "+value, ex);
232 }
233 }
234 }
235
236
237
238
239
240
241
242
243 private static class OctetPattern extends BitSet
244 {
245 private final BitSet _mask = new BitSet(256);
246
247
248
249
250
251
252
253
254 public OctetPattern(String octetSpec)
255 throws IllegalArgumentException
256 {
257 try
258 {
259 if (octetSpec != null)
260 {
261 String spec = octetSpec.trim();
262 if(spec.length() == 0)
263 {
264 _mask.set(0,255);
265 }
266 else
267 {
268 StringTokenizer parts = new StringTokenizer(spec,",");
269 while (parts.hasMoreTokens())
270 {
271 String part = parts.nextToken().trim();
272 if (part.length() > 0)
273 {
274 if (part.indexOf('-') < 0)
275 {
276 Integer value = Integer.valueOf(part);
277 _mask.set(value);
278 }
279 else
280 {
281 int low = 0, high = 255;
282
283 String[] bounds = part.split("-",-2);
284 if (bounds.length != 2)
285 {
286 throw new IllegalArgumentException("Invalid octet spec: "+octetSpec);
287 }
288
289 if (bounds[0].length() > 0)
290 {
291 low = Integer.parseInt(bounds[0]);
292 }
293 if (bounds[1].length() > 0)
294 {
295 high = Integer.parseInt(bounds[1]);
296 }
297
298 if (low > high)
299 {
300 throw new IllegalArgumentException("Invalid octet spec: "+octetSpec);
301 }
302
303 _mask.set(low, high+1);
304 }
305 }
306 }
307 }
308 }
309 }
310 catch (NumberFormatException ex)
311 {
312 throw new IllegalArgumentException("Invalid octet spec: "+octetSpec, ex);
313 }
314 }
315
316
317
318
319
320
321
322
323
324 public boolean match(String value)
325 throws IllegalArgumentException
326 {
327 if (value == null || value.trim().length() == 0)
328 throw new IllegalArgumentException("Invalid octet: "+value);
329
330 try
331 {
332 int number = Integer.parseInt(value);
333 return match(number);
334 }
335 catch (NumberFormatException ex)
336 {
337 throw new IllegalArgumentException("Invalid octet: "+value);
338 }
339 }
340
341
342
343
344
345
346
347
348
349 public boolean match(int number)
350 throws IllegalArgumentException
351 {
352 if (number < 0 || number > 255)
353 throw new IllegalArgumentException("Invalid octet: "+number);
354
355 return _mask.get(number);
356 }
357 }
358 }