KickJava   Java API By Example, From Geeks To Geeks.

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

47
48 public class UniAddress {
49
50     private static final int RESOLVER_WINS = 0;
51     private static final int RESOLVER_BCAST = 1;
52     private static final int RESOLVER_DNS = 2;
53     private static final int RESOLVER_LMHOSTS = 3;
54
55     private static int[] resolveOrder;
56     private static InetAddress JavaDoc baddr;
57
58     private static LogStream log = LogStream.getInstance();
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( log.level > 1 ) {
101                             log.println( "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( log.level > 1 ) {
112                     log.println( "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 hostname 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 isAllDigits( String JavaDoc hostname ) {
228         for (int i = 0; i < hostname.length(); i++) {
229             if (Character.isDigit( hostname.charAt( i )) == false) {
230                 return false;
231             }
232         }
233         return true;
234     }
235
236     /**
237      * Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>. If the
238      * <tt>possibleNTDomainOrWorkgroup</tt> parameter is <tt>true</tt> an
239      * addtional name query will be performed to locate a master browser.
240      */

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

325
326     public UniAddress( Object JavaDoc addr ) {
327         if( addr == null ) {
328             throw new IllegalArgumentException JavaDoc();
329         }
330         this.addr = addr;
331     }
332
333     /**
334      * Return the IP address of this address as a 32 bit integer.
335      */

336
337     public int hashCode() {
338         return addr.hashCode();
339     }
340
341     /**
342      * Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal
343      * if they are both <tt>UniAddress' and refer to the same IP address.
344      */

345
346     public boolean equals( Object JavaDoc obj ) {
347         return obj instanceof UniAddress && addr.hashCode() == obj.hashCode();
348     }
349
350     /**
351      * Guess first called name to try for session establishment. This
352      * method is used exclusively by the <tt>jcifs.smb</tt> package.
353      */

354
355     public String JavaDoc firstCalledName() {
356         if( addr instanceof NbtAddress ) {
357             return ((NbtAddress)addr).firstCalledName();
358         } else {
359             calledName = ((InetAddress JavaDoc)addr).getHostName();
360             if( isDotQuadIP( calledName )) {
361                 calledName = NbtAddress.SMBSERVER_NAME;
362             } else {
363                 int i = calledName.indexOf( '.' );
364                 if( i > 1 && i < 15 ) {
365                     calledName = calledName.substring( 0, i ).toUpperCase();
366                 } else if( calledName.length() > 15 ) {
367                     calledName = NbtAddress.SMBSERVER_NAME;
368                 } else {
369                     calledName = calledName.toUpperCase();
370                 }
371             }
372         }
373
374         return calledName;
375     }
376
377     /**
378      * Guess next called name to try for session establishment. This
379      * method is used exclusively by the <tt>jcifs.smb</tt> package.
380      */

381
382     public String JavaDoc nextCalledName() {
383         if( addr instanceof NbtAddress ) {
384             return ((NbtAddress)addr).nextCalledName();
385         } else if( calledName != NbtAddress.SMBSERVER_NAME ) {
386             calledName = NbtAddress.SMBSERVER_NAME;
387             return calledName;
388         }
389         return null;
390     }
391
392     /**
393      * Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.
394      */

395
396     public Object JavaDoc getAddress() {
397         return addr;
398     }
399
400     /**
401      * Return the hostname of this address such as "MYCOMPUTER".
402      */

403
404     public String JavaDoc getHostName() {
405         if( addr instanceof NbtAddress ) {
406             return ((NbtAddress)addr).getHostName();
407         }
408         return ((InetAddress JavaDoc)addr).getHostName();
409     }
410
411     /**
412      * Return the IP address as text such as "192.168.1.15".
413      */

414
415     public String JavaDoc getHostAddress() {
416         if( addr instanceof NbtAddress ) {
417             return ((NbtAddress)addr).getHostAddress();
418         }
419         return ((InetAddress JavaDoc)addr).getHostAddress();
420     }
421
422     /**
423      * Return the a text representation of this address such as
424      * <tt>MYCOMPUTER/192.168.1.15</tt>.
425      */

426     public String JavaDoc toString() {
427         return addr.toString();
428     }
429 }
430
Popular Tags