KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > NetMatcher


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util;
19
20 import java.net.InetAddress JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24
25 public class NetMatcher
26 {
27     private ArrayList JavaDoc networks;
28
29     public void initInetNetworks(final Collection JavaDoc nets)
30     {
31         networks = new ArrayList JavaDoc();
32         for (Iterator JavaDoc iter = nets.iterator(); iter.hasNext(); ) try
33         {
34             InetNetwork net = InetNetwork.getFromString((String JavaDoc) iter.next());
35             if (!networks.contains(net)) networks.add(net);
36         }
37         catch (java.net.UnknownHostException JavaDoc uhe)
38         {
39             log("Cannot resolve address: " + uhe.getMessage());
40         }
41         networks.trimToSize();
42     }
43
44     public void initInetNetworks(final String JavaDoc[] nets)
45     {
46         networks = new ArrayList JavaDoc();
47         for (int i = 0; i < nets.length; i++) try
48         {
49             InetNetwork net = InetNetwork.getFromString(nets[i]);
50             if (!networks.contains(net)) networks.add(net);
51         }
52         catch (java.net.UnknownHostException JavaDoc uhe)
53         {
54             log("Cannot resolve address: " + uhe.getMessage());
55         }
56         networks.trimToSize();
57     }
58
59     public boolean matchInetNetwork(final String JavaDoc hostIP)
60     {
61         InetAddress JavaDoc ip = null;
62
63         try
64         {
65             ip = org.apache.james.dnsserver.DNSServer.getByName(hostIP);
66         }
67         catch (java.net.UnknownHostException JavaDoc uhe)
68         {
69             log("Cannot resolve address for " + hostIP + ": " + uhe.getMessage());
70         }
71
72         boolean sameNet = false;
73
74         if (ip != null) for (Iterator JavaDoc iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
75         {
76             InetNetwork network = (InetNetwork) iter.next();
77             sameNet = network.contains(ip);
78         }
79         return sameNet;
80     }
81
82     public boolean matchInetNetwork(final InetAddress JavaDoc ip)
83     {
84         boolean sameNet = false;
85
86         for (Iterator JavaDoc iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
87         {
88             InetNetwork network = (InetNetwork) iter.next();
89             sameNet = network.contains(ip);
90         }
91         return sameNet;
92     }
93
94     public NetMatcher()
95     {
96     }
97
98     public NetMatcher(final String JavaDoc[] nets)
99     {
100         initInetNetworks(nets);
101     }
102
103     public NetMatcher(final Collection JavaDoc nets)
104     {
105         initInetNetworks(nets);
106     }
107
108     public String JavaDoc toString() {
109         return networks.toString();
110     }
111
112     protected void log(String JavaDoc s) { }
113 }
114
115 class InetNetwork
116 {
117     /*
118      * Implements network masking, and is compatible with RFC 1518 and
119      * RFC 1519, which describe CIDR: Classless Inter-Domain Routing.
120      */

121
122     private InetAddress JavaDoc network;
123     private InetAddress JavaDoc netmask;
124
125     public InetNetwork(InetAddress JavaDoc ip, InetAddress JavaDoc netmask)
126     {
127         network = maskIP(ip, netmask);
128         this.netmask = netmask;
129     }
130
131     public boolean contains(final String JavaDoc name) throws java.net.UnknownHostException JavaDoc
132     {
133         return network.equals(maskIP(org.apache.james.dnsserver.DNSServer.getByName(name), netmask));
134     }
135
136     public boolean contains(final InetAddress JavaDoc ip)
137     {
138         return network.equals(maskIP(ip, netmask));
139     }
140
141     public String JavaDoc toString()
142     {
143         return network.getHostAddress() + "/" + netmask.getHostAddress();
144     }
145
146     public int hashCode()
147     {
148         return maskIP(network, netmask).hashCode();
149     }
150
151     public boolean equals(Object JavaDoc obj)
152     {
153         return (obj != null) && (obj instanceof InetNetwork) &&
154                 ((((InetNetwork)obj).network.equals(network)) && (((InetNetwork)obj).netmask.equals(netmask)));
155     }
156
157     public static InetNetwork getFromString(String JavaDoc netspec) throws java.net.UnknownHostException JavaDoc
158     {
159         if (netspec.endsWith("*")) netspec = normalizeFromAsterisk(netspec);
160         else
161         {
162             int iSlash = netspec.indexOf('/');
163             if (iSlash == -1) netspec += "/255.255.255.255";
164             else if (netspec.indexOf('.', iSlash) == -1) netspec = normalizeFromCIDR(netspec);
165         }
166
167         return new InetNetwork(org.apache.james.dnsserver.DNSServer.getByName(netspec.substring(0, netspec.indexOf('/'))),
168                                org.apache.james.dnsserver.DNSServer.getByName(netspec.substring(netspec.indexOf('/') + 1)));
169     }
170
171     public static InetAddress JavaDoc maskIP(final byte[] ip, final byte[] mask)
172     {
173         try
174         {
175             return getByAddress(new byte[]
176             {
177                 (byte) (mask[0] & ip[0]),
178                 (byte) (mask[1] & ip[1]),
179                 (byte) (mask[2] & ip[2]),
180                 (byte) (mask[3] & ip[3])
181             });
182         }
183         catch(Exception JavaDoc _) {}
184         {
185             return null;
186         }
187     }
188
189     public static InetAddress JavaDoc maskIP(final InetAddress JavaDoc ip, final InetAddress JavaDoc mask)
190     {
191         return maskIP(ip.getAddress(), mask.getAddress());
192     }
193
194     /*
195      * This converts from an uncommon "wildcard" CIDR format
196      * to "address + mask" format:
197      *
198      * * => 000.000.000.0/000.000.000.0
199      * xxx.* => xxx.000.000.0/255.000.000.0
200      * xxx.xxx.* => xxx.xxx.000.0/255.255.000.0
201      * xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0
202      */

203     static private String JavaDoc normalizeFromAsterisk(final String JavaDoc netspec)
204     {
205         String JavaDoc[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" };
206         char[] srcb = netspec.toCharArray();
207         int octets = 0;
208         for (int i = 1; i < netspec.length(); i++) {
209             if (srcb[i] == '.') octets++;
210         }
211         return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]);
212     }
213
214     /*
215      * RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR)
216      * This converts from "prefix + prefix-length" format to
217      * "address + mask" format, e.g. from xxx.xxx.xxx.xxx/yy
218      * to xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy.
219      */

220     static private String JavaDoc normalizeFromCIDR(final String JavaDoc netspec)
221     {
222         final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1));
223         final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1);
224
225         return netspec.substring(0, netspec.indexOf('/') + 1) +
226                 Integer.toString(mask >> 24 & 0xFF, 10) + "." +
227                 Integer.toString(mask >> 16 & 0xFF, 10) + "." +
228                 Integer.toString(mask >> 8 & 0xFF, 10) + "." +
229                 Integer.toString(mask >> 0 & 0xFF, 10);
230     }
231
232     private static java.lang.reflect.Method JavaDoc getByAddress = null;
233
234     static {
235         try {
236             Class JavaDoc inetAddressClass = Class.forName("java.net.InetAddress");
237             Class JavaDoc[] parameterTypes = { byte[].class };
238             getByAddress = inetAddressClass.getMethod("getByAddress", parameterTypes);
239         } catch (Exception JavaDoc e) {
240             getByAddress = null;
241         }
242     }
243
244     private static InetAddress JavaDoc getByAddress(byte[] ip) throws java.net.UnknownHostException JavaDoc
245     {
246         InetAddress JavaDoc addr = null;
247         if (getByAddress != null) try {
248             addr = (InetAddress JavaDoc) getByAddress.invoke(null, new Object JavaDoc[] { ip });
249         } catch (IllegalAccessException JavaDoc e) {
250         } catch (java.lang.reflect.InvocationTargetException JavaDoc e) {
251         }
252
253         if (addr == null) {
254             addr = InetAddress.getByName
255                    (
256                     Integer.toString(ip[0] & 0xFF, 10) + "." +
257                     Integer.toString(ip[1] & 0xFF, 10) + "." +
258                     Integer.toString(ip[2] & 0xFF, 10) + "." +
259                     Integer.toString(ip[3] & 0xFF, 10)
260                    );
261         }
262         return addr;
263     }
264 }
265
Popular Tags