KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > jcifs > UniAddress


1 /* jcifs smb client library in Java
2  * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package com.knowgate.jcifs;
20
21 import java.net.InetAddress JavaDoc;
22 import java.net.UnknownHostException JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25 import com.knowgate.jcifs.netbios.NbtAddress;
26 import com.knowgate.jcifs.netbios.Lmhosts;
27
28 import com.knowgate.debug.*;
29
30 /**
31  * <p>Under normal conditions it is not necessary to use
32  * this class to use jCIFS properly. Name resolusion is
33  * handled internally to the <code>jcifs.smb</code> package.
34  * <p>
35  * This class is a wrapper for both {@link jcifs.netbios.NbtAddress}
36  * and {@link java.net.InetAddress}. The name resolution mechanisms
37  * used will systematically query all available configured resolution
38  * services including WINS, broadcasts, DNS, and LMHOSTS. See
39  * <a HREF="../../resolver.html">Setting Name Resolution Properties</a>
40  * and the <code>jcifs.resolveOrder</code> property. Changing
41  * jCIFS name resolution properties can greatly affect the behavior of
42  * the client and may be necessary for proper operation.
43  * <p>
44  * This class should be used in favor of <tt>InetAddress</tt> to resolve
45  * hostnames on LANs and WANs that support a mixture of NetBIOS/WINS and
46  * DNS resolvable hosts.
47  */

48
49 public class UniAddress {
50
51     private static final int RESOLVER_WINS = 0;
52     private static final int RESOLVER_BCAST = 1;
53     private static final int RESOLVER_DNS = 2;
54     private static final int RESOLVER_LMHOSTS = 3;
55
56     private static int[] resolveOrder;
57     private static InetAddress JavaDoc baddr;
58
59
60     static {
61         String JavaDoc ro = Config.getProperty( "jcifs.resolveOrder" );
62         InetAddress JavaDoc nbns = NbtAddress.getWINSAddress();
63
64         try {
65             baddr = Config.getInetAddress( "jcifs.netbios.baddr",
66                                 InetAddress.getByName( "255.255.255.255" ));
67         } catch( UnknownHostException JavaDoc uhe ) {
68         }
69
70         if( ro == null || ro.length() == 0 ) {
71
72             /* No resolveOrder has been specified, use the
73              * default which is LMHOSTS,WINS,BCAST,DNS or just
74              * LMHOSTS,BCAST,DNS if jcifs.netbios.wins has not
75              * been specified.
76              */

77
78             if( nbns == null ) {
79                 resolveOrder = new int[3];
80                 resolveOrder[0] = RESOLVER_LMHOSTS;
81                 resolveOrder[1] = RESOLVER_BCAST;
82                 resolveOrder[2] = RESOLVER_DNS;
83             } else {
84                 resolveOrder = new int[4];
85                 resolveOrder[0] = RESOLVER_LMHOSTS;
86                 resolveOrder[1] = RESOLVER_WINS;
87                 resolveOrder[2] = RESOLVER_BCAST;
88                 resolveOrder[3] = RESOLVER_DNS;
89             }
90         } else {
91             int[] tmp = new int[4];
92             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc( ro, "," );
93             int i = 0;
94             while( st.hasMoreTokens() ) {
95                 String JavaDoc s = st.nextToken().trim();
96                 if( s.equalsIgnoreCase( "LMHOSTS" )) {
97                     tmp[i++] = RESOLVER_LMHOSTS;
98                 } else if( s.equalsIgnoreCase( "WINS" )) {
99                     if( nbns == null ) {
100                         if( DebugFile.trace ) {
101                             DebugFile.writeln( "UniAddress resolveOrder specifies WINS however the " +
102                                     "jcifs.netbios.wins property has not been set" );
103                         }
104                         continue;
105                     }
106                     tmp[i++] = RESOLVER_WINS;
107                 } else if( s.equalsIgnoreCase( "BCAST" )) {
108                     tmp[i++] = RESOLVER_BCAST;
109                 } else if( s.equalsIgnoreCase( "DNS" )) {
110                     tmp[i++] = RESOLVER_DNS;
111                 } else if( DebugFile.trace ) {
112                     DebugFile.writeln( "unknown resolver method: " + s );
113                 }
114             }
115             resolveOrder = new int[i];
116             System.arraycopy( tmp, 0, resolveOrder, 0, i );
117         }
118     }
119
120     static class Sem {
121         Sem( int count ) {
122             this.count = count;
123         }
124         int count;
125     }
126
127     static class QueryThread extends Thread JavaDoc {
128
129         Sem sem;
130         String JavaDoc host, scope;
131         int type;
132         NbtAddress ans = null;
133         InetAddress JavaDoc svr;
134         UnknownHostException JavaDoc uhe;
135
136         QueryThread( Sem sem, String JavaDoc host, int type,
137                         String JavaDoc scope, InetAddress JavaDoc svr ) {
138             super( "JCIFS-QueryThread: " + host );
139             this.sem = sem;
140             this.host = host;
141             this.type = type;
142             this.scope = scope;
143             this.svr = svr;
144         }
145         public void run() {
146             try {
147                 ans = NbtAddress.getByName( host, type, scope, svr );
148             } catch( UnknownHostException JavaDoc uhe ) {
149                 this.uhe = uhe;
150             } catch( Exception JavaDoc ex ) {
151                 this.uhe = new UnknownHostException JavaDoc( ex.getMessage() );
152             } finally {
153                 synchronized( sem ) {
154                     sem.count--;
155                     sem.notify();
156                 }
157             }
158         }
159     }
160
161     static NbtAddress lookupServerOrWorkgroup( String JavaDoc name, InetAddress JavaDoc svr )
162                                                     throws UnknownHostException JavaDoc {
163         Sem sem = new Sem( 2 );
164         int type = NbtAddress.isWINS( svr ) ? 0x1b : 0x1d;
165
166         QueryThread q1x = new QueryThread( sem, name, type, null, svr );
167         QueryThread q20 = new QueryThread( sem, name, 0x20, null, svr );
168         q1x.setDaemon( true );
169         q20.setDaemon( true );
170         try {
171             synchronized( sem ) {
172                 q1x.start();
173                 q20.start();
174
175                 while( sem.count > 0 && q1x.ans == null && q20.ans == null ) {
176                     sem.wait();
177                 }
178             }
179         } catch( InterruptedException JavaDoc ie ) {
180             throw new UnknownHostException JavaDoc( name );
181         }
182         if( q1x.ans != null ) {
183             return q1x.ans;
184         } else if( q20.ans != null ) {
185             return q20.ans;
186         } else {
187             throw q1x.uhe;
188         }
189     }
190
191     /**
192      * Determines the address of a host given it's host name. The name can be a
193      * machine name like "jcifs.samba.org", or an IP address like "192.168.1.15".
194      *
195      * @param host NetBIOS or DNS hostname to resolve
196      * @throws java.net.UnknownHostException if there is an error resolving the name
197      */

198
199     public static UniAddress getByName( String JavaDoc hostname )
200                                         throws UnknownHostException JavaDoc {
201         return getByName( hostname, false );
202     }
203
204     static boolean isDotQuadIP( String JavaDoc hostname ) {
205         if( Character.isDigit( hostname.charAt( 0 ))) {
206             int i, len, dots;
207             char[] data;
208
209             i = dots = 0; /* quick IP address validation */
210             len = hostname.length();
211             data = hostname.toCharArray();
212             while( i < len && Character.isDigit( data[i++] )) {
213                 if( i == len && dots == 3 ) {
214                     // probably an IP address
215
return true;
216                 }
217                 if( i < len && data[i] == '.' ) {
218                     dots++;
219                     i++;
220                 }
221             }
222         }
223
224         return false;
225     }
226
227     static boolean isValidDnsName( String JavaDoc hostname ) {
228         // Simple for now. Just handles "1" --> 1/0.0.0.1 kind of stuff
229
return Character.isDigit( hostname.charAt( 0 )) == false;
230     }
231
232     /**
233      * Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>. If the
234      * <tt>possibleNTDomainOrWorkgroup</tt> parameter is <tt>true</tt> an
235      * addtional name query will be performed to locate a master browser.
236      */

237
238     public static UniAddress getByName( String JavaDoc hostname,
239                                         boolean possibleNTDomainOrWorkgroup )
240                                         throws UnknownHostException JavaDoc {
241         Object JavaDoc addr;
242         int i;
243
244         if( hostname == null || hostname.length() == 0 ) {
245             throw new UnknownHostException JavaDoc();
246         }
247
248         if( isDotQuadIP( hostname )) {
249             return new UniAddress( NbtAddress.getByName( hostname ));
250         }
251
252         for( i = 0; i < resolveOrder.length; i++ ) {
253             try {
254                 switch( resolveOrder[i] ) {
255                     case RESOLVER_LMHOSTS:
256                         if(( addr = Lmhosts.getByName( hostname )) == null ) {
257                             continue;
258                         }
259                         break;
260                     case RESOLVER_WINS:
261                         if( hostname == NbtAddress.MASTER_BROWSER_NAME ||
262                                                     hostname.length() > 15 ) {
263                                                     // invalid netbios name
264
continue;
265                         }
266                         if( possibleNTDomainOrWorkgroup ) {
267                             addr = lookupServerOrWorkgroup( hostname, NbtAddress.getWINSAddress() );
268                         } else {
269                             addr = NbtAddress.getByName( hostname, 0x20, null, NbtAddress.getWINSAddress() );
270                         }
271                         break;
272                     case RESOLVER_BCAST:
273                         if( hostname.length() > 15 ) {
274                             // invalid netbios name
275
continue;
276                         }
277                         if( possibleNTDomainOrWorkgroup ) {
278                             addr = lookupServerOrWorkgroup( hostname, baddr );
279                         } else {
280                             addr = NbtAddress.getByName( hostname, 0x20, null, baddr );
281                         }
282                         break;
283                     case RESOLVER_DNS:
284                         if( isValidDnsName( hostname ) == false ) {
285                             throw new UnknownHostException JavaDoc( hostname );
286                         }
287                         addr = InetAddress.getByName( hostname );
288                         break;
289                     default:
290                         throw new UnknownHostException JavaDoc( hostname );
291                 }
292                 return new UniAddress( addr ); // Success
293
} catch( IOException JavaDoc ioe ) {
294                 // Failure
295
}
296         }
297         throw new UnknownHostException JavaDoc( hostname );
298     }
299
300     Object JavaDoc addr;
301     String JavaDoc calledName;
302
303     /**
304      * Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or
305      * <tt>NbtAddress</tt>.
306      */

307
308     public UniAddress( Object JavaDoc addr ) {
309         if( addr == null ) {
310             throw new IllegalArgumentException JavaDoc();
311         }
312         this.addr = addr;
313     }
314
315     /**
316      * Return the IP address of this address as a 32 bit integer.
317      */

318
319     public int hashCode() {
320         return addr.hashCode();
321     }
322
323     /**
324      * Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal
325      * if they are both <tt>UniAddress' and refer to the same IP address.
326      */

327
328     public boolean equals( Object JavaDoc obj ) {
329         return obj instanceof UniAddress && addr.hashCode() == obj.hashCode();
330     }
331
332     /**
333      * Guess first called name to try for session establishment. This
334      * method is used exclusively by the <tt>jcifs.smb</tt> package.
335      */

336
337     public String JavaDoc firstCalledName() {
338         if( addr instanceof NbtAddress ) {
339             return ((NbtAddress)addr).firstCalledName();
340         } else {
341             calledName = ((InetAddress JavaDoc)addr).getHostName();
342             if( isDotQuadIP( calledName )) {
343                 calledName = NbtAddress.SMBSERVER_NAME;
344             } else {
345                 int i = calledName.indexOf( '.' );
346                 if( i > 1 && i < 15 ) {
347                     calledName = calledName.substring( 0, i ).toUpperCase();
348                 } else if( calledName.length() > 15 ) {
349                     calledName = NbtAddress.SMBSERVER_NAME;
350                 } else {
351                     calledName = calledName.toUpperCase();
352                 }
353             }
354         }
355
356         return calledName;
357     }
358
359     /**
360      * Guess next called name to try for session establishment. This
361      * method is used exclusively by the <tt>jcifs.smb</tt> package.
362      */

363
364     public String JavaDoc nextCalledName() {
365         if( addr instanceof NbtAddress ) {
366             return ((NbtAddress)addr).nextCalledName();
367         } else if( calledName != NbtAddress.SMBSERVER_NAME ) {
368             calledName = NbtAddress.SMBSERVER_NAME;
369             return calledName;
370         }
371         return null;
372     }
373
374     /**
375      * Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.
376      */

377
378     public Object JavaDoc getAddress() {
379         return addr;
380     }
381
382     /**
383      * Return the hostname of this address such as "MYCOMPUTER".
384      */

385
386     public String JavaDoc getHostName() {
387         if( addr instanceof NbtAddress ) {
388             return ((NbtAddress)addr).getHostName();
389         }
390         return ((InetAddress JavaDoc)addr).getHostName();
391     }
392
393     /**
394      * Return the IP address as text such as "192.168.1.15".
395      */

396
397     public String JavaDoc getHostAddress() {
398         if( addr instanceof NbtAddress ) {
399             return ((NbtAddress)addr).getHostAddress();
400         }
401         return ((InetAddress JavaDoc)addr).getHostAddress();
402     }
403
404     /**
405      * Return the a text representation of this address such as
406      * <tt>MYCOMPUTER/192.168.1.15</tt>.
407      */

408     public String JavaDoc toString() {
409         return addr.toString();
410     }
411 }
412
Popular Tags