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