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