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