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