KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > netbios > NbtAddress


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.netbios;
20
21 import java.net.InetAddress JavaDoc;
22 import java.net.UnknownHostException JavaDoc;
23 import java.net.SocketException JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.UnsupportedEncodingException JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import jcifs.Config;
28 import jcifs.util.Hexdump;
29
30 /**
31  * This class represents a NetBIOS over TCP/IP address. Under normal
32  * conditions, users of jCIFS need not be concerned with this class as
33  * name resolution and session services are handled internally by the smb package.
34  *
35  * <p> Applications can use the methods <code>getLocalHost</code>,
36  * <code>getByName</code>, and
37  * <code>getAllByAddress</code> to create a new NbtAddress instance. This
38  * class is symmetric with {@link java.net.InetAddress}.
39  *
40  * <p><b>About NetBIOS:</b> The NetBIOS name
41  * service is a dynamic distributed service that allows hosts to resolve
42  * names by broadcasting a query, directing queries to a server such as
43  * Samba or WINS. NetBIOS is currently the primary networking layer for
44  * providing name service, datagram service, and session service to the
45  * Microsoft Windows platform. A NetBIOS name can be 15 characters long
46  * and hosts usually registers several names on the network. From a
47  * Windows command prompt you can see
48  * what names a host registers with the nbtstat command.
49  * <p><blockquote><pre>
50  * C:\>nbtstat -a 192.168.1.15
51  *
52  * NetBIOS Remote Machine Name Table
53  *
54  * Name Type Status
55  * ---------------------------------------------
56  * JMORRIS2 <00> UNIQUE Registered
57  * BILLING-NY <00> GROUP Registered
58  * JMORRIS2 <03> UNIQUE Registered
59  * JMORRIS2 <20> UNIQUE Registered
60  * BILLING-NY <1E> GROUP Registered
61  * JMORRIS <03> UNIQUE Registered
62  *
63  * MAC Address = 00-B0-34-21-FA-3B
64  * </blockquote></pre>
65  * <p> The hostname of this machine is <code>JMORRIS2</code>. It is
66  * a member of the group(a.k.a workgroup and domain) <code>BILLING-NY</code>. To
67  * obtain an {@link java.net.InetAddress} for a host one might do:
68  *
69  * <pre>
70  * InetAddress addr = NbtAddress.getByName( "jmorris2" ).getInetAddress();
71  * </pre>
72  * <p>From a UNIX platform with Samba installed you can perform similar
73  * diagnostics using the <code>nmblookup</code> utility.
74  *
75  * @author Michael B. Allen
76  * @see java.net.InetAddress
77  * @since jcifs-0.1
78  */

79
80 public final class NbtAddress {
81
82 /*
83  * This is a special name that means all hosts. If you wish to find all hosts
84  * on a network querying a workgroup group name is the preferred method.
85  */

86
87     static final String JavaDoc ANY_HOSTS_NAME = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000";
88
89 /**
90  * This is a special name for querying the master browser that serves the
91  * list of hosts found in "Network Neighborhood".
92  */

93
94     public static final String JavaDoc MASTER_BROWSER_NAME = "\u0001\u0002__MSBROWSE__\u0002";
95
96 /**
97  * A special generic name specified when connecting to a host for which
98  * a name is not known. Not all servers respond to this name.
99  */

100
101     public static final String JavaDoc SMBSERVER_NAME = "*SMBSERVER ";
102
103 /**
104  * A B node only broadcasts name queries. This is the default if a
105  * nameserver such as WINS or Samba is not specified.
106  */

107
108     public static final int B_NODE = 0;
109
110 /**
111  * A Point-to-Point node, or P node, unicasts queries to a nameserver
112  * only. Natrually the <code>jcifs.netbios.nameserver</code> property must
113  * be set.
114  */

115
116     public static final int P_NODE = 1;
117
118 /**
119  * Try Broadcast queries first, then try to resolve the name using the
120  * nameserver.
121  */

122
123     public static final int M_NODE = 2;
124
125 /**
126  * A Hybrid node tries to resolve a name using the nameserver first. If
127  * that fails use the broadcast address. This is the default if a nameserver
128  * is provided. This is the behavior of Microsoft Windows machines.
129  */

130
131     public static final int H_NODE = 3;
132
133     static final InetAddress JavaDoc[] NBNS = Config.getInetAddressArray( "jcifs.netbios.wins", ",", new InetAddress JavaDoc[0] );
134
135     /* Construct the shared static client object that will
136      * conduct all encoding and decoding of NetBIOS name service
137      * messages as well as socket IO in a synchronized fashon.
138      */

139
140     private static final NameServiceClient CLIENT = new NameServiceClient();
141
142     private static final int DEFAULT_CACHE_POLICY = 30;
143     private static final int CACHE_POLICY = Config.getInt( "jcifs.netbios.cachePolicy", DEFAULT_CACHE_POLICY );
144     private static final int FOREVER = -1;
145     private static int nbnsIndex = 0;
146
147     private static final HashMap JavaDoc ADDRESS_CACHE = new HashMap JavaDoc();
148     private static final HashMap JavaDoc LOOKUP_TABLE = new HashMap JavaDoc();
149
150     static final Name UNKNOWN_NAME = new Name( "0.0.0.0", 0x00, null );
151     static final NbtAddress UNKNOWN_ADDRESS = new NbtAddress( UNKNOWN_NAME, 0, false, B_NODE );
152     static final byte[] UNKNOWN_MAC_ADDRESS = new byte[] {
153         (byte)0x00, (byte)0x00, (byte)0x00,
154         (byte)0x00, (byte)0x00, (byte)0x00
155     };
156
157     static final class CacheEntry {
158         Name hostName;
159         NbtAddress address;
160         long expiration;
161
162         CacheEntry( Name hostName, NbtAddress address, long expiration ) {
163             this.hostName = hostName;
164             this.address = address;
165             this.expiration = expiration;
166         }
167     }
168
169     static NbtAddress localhost;
170
171     static {
172         InetAddress JavaDoc localInetAddress;
173         String JavaDoc localHostname;
174         Name localName;
175
176         /* Create an address to represent failed lookups and cache forever.
177          */

178
179         ADDRESS_CACHE.put( UNKNOWN_NAME, new CacheEntry( UNKNOWN_NAME, UNKNOWN_ADDRESS, FOREVER ));
180
181         /* Determine the InetAddress of the local interface
182          * if one was not specified.
183          */

184         localInetAddress = CLIENT.laddr;
185         if( localInetAddress == null ) {
186             try {
187                 localInetAddress = InetAddress.getLocalHost();
188             } catch( UnknownHostException JavaDoc uhe ) {
189             }
190         }
191
192         /* If a local hostname was not provided a name like
193          * JCIFS34_172_A6 will be dynamically generated for the
194          * client. This is primarily (exclusively?) used as a
195          * CallingName during session establishment.
196          */

197         localHostname = Config.getProperty( "jcifs.netbios.hostname", null );
198         if( localHostname == null || localHostname.length() == 0 ) {
199             byte[] addr = localInetAddress.getAddress();
200             localHostname = "JCIFS" +
201                     ( addr[2] & 0xFF ) + "_" +
202                     ( addr[3] & 0xFF ) + "_" +
203                     Hexdump.toHexString( (int)( Math.random() * (double)0xFF ), 2 );
204         }
205
206         /* Create an NbtAddress for the local interface with
207          * the name deduced above possibly with scope applied and
208          * cache it forever.
209          */

210         localName = new Name( localHostname, 0x00,
211                             Config.getProperty( "jcifs.netbios.scope", null ));
212         localhost = new NbtAddress( localName,
213                                     localInetAddress.hashCode(),
214                                     false,
215                                     B_NODE,
216                                     false, false, true, false,
217                                     UNKNOWN_MAC_ADDRESS );
218         cacheAddress( localName, localhost, FOREVER );
219     }
220
221     static void cacheAddress( Name hostName, NbtAddress addr ) {
222         if( CACHE_POLICY == 0 ) {
223             return;
224         }
225         long expiration = -1;
226         if( CACHE_POLICY != FOREVER ) {
227             expiration = System.currentTimeMillis() + CACHE_POLICY * 1000;
228         }
229         cacheAddress( hostName, addr, expiration );
230     }
231     static void cacheAddress( Name hostName, NbtAddress addr, long expiration ) {
232         if( CACHE_POLICY == 0 ) {
233             return;
234         }
235         synchronized( ADDRESS_CACHE ) {
236             CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName );
237             if( entry == null ) {
238                 entry = new CacheEntry( hostName, addr, expiration );
239                 ADDRESS_CACHE.put( hostName, entry );
240             } else {
241                 entry.address = addr;
242                 entry.expiration = expiration;
243             }
244         }
245     }
246     static void cacheAddressArray( NbtAddress[] addrs ) {
247         if( CACHE_POLICY == 0 ) {
248             return;
249         }
250         long expiration = -1;
251         if( CACHE_POLICY != FOREVER ) {
252             expiration = System.currentTimeMillis() + CACHE_POLICY * 1000;
253         }
254         synchronized( ADDRESS_CACHE ) {
255             for( int i = 0; i < addrs.length; i++ ) {
256                 CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( addrs[i].hostName );
257                 if( entry == null ) {
258                     entry = new CacheEntry( addrs[i].hostName, addrs[i], expiration );
259                     ADDRESS_CACHE.put( addrs[i].hostName, entry );
260                 } else {
261                     entry.address = addrs[i];
262                     entry.expiration = expiration;
263                 }
264             }
265         }
266     }
267     static NbtAddress getCachedAddress( Name hostName ) {
268         if( CACHE_POLICY == 0 ) {
269             return null;
270         }
271         synchronized( ADDRESS_CACHE ) {
272             CacheEntry entry = (CacheEntry)ADDRESS_CACHE.get( hostName );
273             if( entry != null && entry.expiration < System.currentTimeMillis() &&
274                                                 entry.expiration >= 0 ) {
275                 entry = null;
276             }
277             return entry != null ? entry.address : null;
278         }
279     }
280
281     static NbtAddress doNameQuery( Name name, InetAddress JavaDoc svr )
282                                                     throws UnknownHostException JavaDoc {
283         NbtAddress addr;
284
285         if( name.hexCode == 0x1d && svr == null ) {
286             svr = CLIENT.baddr; // bit of a hack but saves a lookup
287
}
288         name.srcHashCode = svr != null ? svr.hashCode() : 0;
289         addr = getCachedAddress( name );
290
291         if( addr == null ) {
292             /* This was copied amost verbatim from InetAddress.java. See the
293              * comments there for a description of how the LOOKUP_TABLE prevents
294              * redundant queries from going out on the wire.
295              */

296             if(( addr = (NbtAddress)checkLookupTable( name )) == null ) {
297                 try {
298                     addr = CLIENT.getByName( name, svr );
299                 } catch( UnknownHostException JavaDoc uhe ) {
300                     addr = UNKNOWN_ADDRESS;
301                 } finally {
302                     cacheAddress( name, addr );
303                     updateLookupTable( name );
304                 }
305             }
306         }
307         if( addr == UNKNOWN_ADDRESS ) {
308             throw new UnknownHostException JavaDoc( name.toString() );
309         }
310         return addr;
311     }
312
313     private static Object JavaDoc checkLookupTable( Name name ) {
314         Object JavaDoc obj;
315
316         synchronized( LOOKUP_TABLE ) {
317             if( LOOKUP_TABLE.containsKey( name ) == false ) {
318                 LOOKUP_TABLE.put( name, name );
319                 return null;
320             }
321             while( LOOKUP_TABLE.containsKey( name )) {
322                 try {
323                     LOOKUP_TABLE.wait();
324                 } catch( InterruptedException JavaDoc e ) {
325                 }
326             }
327         }
328         obj = getCachedAddress( name );
329         if( obj == null ) {
330             synchronized( LOOKUP_TABLE ) {
331                 LOOKUP_TABLE.put( name, name );
332             }
333         }
334
335         return obj;
336     }
337     private static void updateLookupTable( Name name ) {
338         synchronized( LOOKUP_TABLE ) {
339             LOOKUP_TABLE.remove( name );
340             LOOKUP_TABLE.notifyAll();
341         }
342     }
343
344 /**
345  * Retrieves the local host address.
346  *
347  * @throws UnknownHostException This is not likely as the IP returned
348  * by <code>InetAddress</code> should be available
349  */

350
351     public static NbtAddress getLocalHost() throws UnknownHostException JavaDoc {
352         return localhost;
353     }
354     public static Name getLocalName() {
355         return localhost.hostName;
356     }
357
358 /**
359  * Determines the address of a host given it's host name. The name can be a NetBIOS name like
360  * "freto" or an IP address like "192.168.1.15". It cannot be a DNS name;
361  * the analygous {@link jcifs.UniAddress} or {@link java.net.InetAddress}
362  * <code>getByName</code> methods can be used for that.
363  *
364  * @param host hostname to resolve
365  * @throws java.net.UnknownHostException if there is an error resolving the name
366  */

367
368     public static NbtAddress getByName( String JavaDoc host )
369                                         throws UnknownHostException JavaDoc {
370         return getByName( host, 0x00, null );
371     }
372
373 /**
374  * Determines the address of a host given it's host name. NetBIOS
375  * names also have a <code>type</code>. Types(aka Hex Codes)
376  * are used to distiquish the various services on a host. <a
377  * HREF="../../../nbtcodes.html">Here</a> is
378  * a fairly complete list of NetBIOS hex codes. Scope is not used but is
379  * still functional in other NetBIOS products and so for completeness it has been
380  * implemented. A <code>scope</code> of <code>null</code> or <code>""</code>
381  * signifies no scope.
382  *
383  * @param host the name to resolve
384  * @param type the hex code of the name
385  * @param scope the scope of the name
386  * @throws java.net.UnknownHostException if there is an error resolving the name
387  */

388
389     public static NbtAddress getByName( String JavaDoc host,
390                                         int type,
391                                         String JavaDoc scope )
392                                         throws UnknownHostException JavaDoc {
393
394         return getByName( host, type, scope, null );
395     }
396
397 /*
398  * The additional <code>svr</code> parameter specifies the address to
399  * query. This might be the address of a specific host, a name server,
400  * or a broadcast address.
401  */

402
403     public static NbtAddress getByName( String JavaDoc host,
404                                         int type,
405                                         String JavaDoc scope,
406                                         InetAddress JavaDoc svr )
407                                         throws UnknownHostException JavaDoc {
408
409         if( host == null || host.length() == 0 ) {
410             return getLocalHost();
411         }
412         if( !Character.isDigit( host.charAt(0) )) {
413             return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr );
414         } else {
415             int IP = 0x00;
416             int hitDots = 0;
417             char[] data = host.toCharArray();
418
419             for( int i = 0; i < data.length; i++ ) {
420                 char c = data[i];
421                 if( c < 48 || c > 57 ) {
422                     return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr );
423                 }
424                 int b = 0x00;
425                 while( c != '.' ) {
426                     if( c < 48 || c > 57 ) {
427                         return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr );
428                     }
429                     b = b * 10 + c - '0';
430
431                     if( ++i >= data.length )
432                         break;
433
434                     c = data[i];
435                 }
436                 if( b > 0xFF ) {
437                     return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr );
438                 }
439                 IP = ( IP << 8 ) + b;
440                 hitDots++;
441             }
442             if( hitDots != 4 || host.endsWith( "." )) {
443                 return (NbtAddress)doNameQuery( new Name( host, type, scope ), svr );
444             }
445             return new NbtAddress( UNKNOWN_NAME, IP, false, B_NODE );
446         }
447     }
448
449     public static NbtAddress[] getAllByName( String JavaDoc host,
450                                         int type,
451                                         String JavaDoc scope,
452                                         InetAddress JavaDoc svr )
453                                         throws UnknownHostException JavaDoc {
454         return CLIENT.getAllByName( new Name( host, type, scope ), svr );
455     }
456
457 /**
458  * Retrieve all addresses of a host by it's address. NetBIOS hosts can
459  * have many names for a given IP address. The name and IP address make the
460  * NetBIOS address. This provides a way to retrieve the other names for a
461  * host with the same IP address.
462  *
463  * @param host hostname to lookup all addresses for
464  * @throws java.net.UnknownHostException if there is an error resolving the name
465  */

466
467
468     public static NbtAddress[] getAllByAddress( String JavaDoc host )
469                                                 throws UnknownHostException JavaDoc {
470         return getAllByAddress( getByName( host, 0x00, null ));
471     }
472
473
474 /**
475  * Retrieve all addresses of a host by it's address. NetBIOS hosts can
476  * have many names for a given IP address. The name and IP address make
477  * the NetBIOS address. This provides a way to retrieve the other names
478  * for a host with the same IP address. See {@link #getByName}
479  * for a description of <code>type</code>
480  * and <code>scope</code>.
481  *
482  * @param host hostname to lookup all addresses for
483  * @param type the hexcode of the name
484  * @param scope the scope of the name
485  * @throws java.net.UnknownHostException if there is an error resolving the name
486  */

487
488
489     public static NbtAddress[] getAllByAddress( String JavaDoc host,
490                                         int type,
491                                         String JavaDoc scope )
492                                         throws UnknownHostException JavaDoc {
493         return getAllByAddress( getByName( host, type, scope ));
494     }
495
496
497 /**
498  * Retrieve all addresses of a host by it's address. NetBIOS hosts can
499  * have many names for a given IP address. The name and IP address make the
500  * NetBIOS address. This provides a way to retrieve the other names for a
501  * host with the same IP address.
502  *
503  * @param addr the address to query
504  * @throws UnknownHostException if address cannot be resolved
505  */

506
507     public static NbtAddress[] getAllByAddress( NbtAddress addr )
508                                                 throws UnknownHostException JavaDoc {
509         try {
510             NbtAddress[] addrs = CLIENT.getNodeStatus( addr );
511             cacheAddressArray( addrs );
512             return addrs;
513         } catch( UnknownHostException JavaDoc uhe ) {
514             throw new UnknownHostException JavaDoc( "no name with type 0x" +
515                             Hexdump.toHexString( addr.hostName.hexCode, 2 ) +
516                             ((( addr.hostName.scope == null ) ||
517                             ( addr.hostName.scope.length() == 0 )) ?
518                             " with no scope" : " with scope " + addr.hostName.scope ) +
519                             " for host " + addr.getHostAddress() );
520         }
521     }
522
523     public static InetAddress JavaDoc getWINSAddress() {
524         return NBNS.length == 0 ? null : NBNS[nbnsIndex];
525     }
526     public static boolean isWINS( InetAddress JavaDoc svr ) {
527         for( int i = 0; svr != null && i < NBNS.length; i++ ) {
528             if( svr.hashCode() == NBNS[i].hashCode() ) {
529                 return true;
530             }
531         }
532         return false;
533     }
534     static InetAddress JavaDoc switchWINS() {
535         nbnsIndex = (nbnsIndex + 1) < NBNS.length ? nbnsIndex + 1 : 0;
536         return NBNS.length == 0 ? null : NBNS[nbnsIndex];
537     }
538
539     Name hostName;
540     int address, nodeType;
541     boolean groupName,
542         isBeingDeleted,
543         isInConflict,
544         isActive,
545         isPermanent,
546         isDataFromNodeStatus;
547     byte[] macAddress;
548     String JavaDoc calledName;
549
550     NbtAddress( Name hostName, int address, boolean groupName, int nodeType ) {
551         this.hostName = hostName;
552         this.address = address;
553         this.groupName = groupName;
554         this.nodeType = nodeType;
555     }
556
557     NbtAddress( Name hostName,
558                 int address,
559                 boolean groupName,
560                 int nodeType,
561                 boolean isBeingDeleted,
562                 boolean isInConflict,
563                 boolean isActive,
564                 boolean isPermanent,
565                 byte[] macAddress ) {
566
567 /* The NodeStatusResponse.readNodeNameArray method may also set this
568  * information. These two places where node status data is populated should
569  * be consistent. Be carefull!
570  */

571         this.hostName = hostName;
572         this.address = address;
573         this.groupName = groupName;
574         this.nodeType = nodeType;
575         this.isBeingDeleted = isBeingDeleted;
576         this.isInConflict = isInConflict;
577         this.isActive = isActive;
578         this.isPermanent = isPermanent;
579         this.macAddress = macAddress;
580         isDataFromNodeStatus = true;
581     }
582
583 /* Guess next called name to try for session establishment. These
584  * methods are used by the smb package.
585  */

586
587     public String JavaDoc firstCalledName() {
588
589         calledName = hostName.name;
590
591         if( Character.isDigit( calledName.charAt( 0 ))) {
592             int i, len, dots;
593             char[] data;
594
595             i = dots = 0; /* quick IP address validation */
596             len = calledName.length();
597             data = calledName.toCharArray();
598             while( i < len && Character.isDigit( data[i++] )) {
599                 if( i == len && dots == 3 ) {
600                     // probably an IP address
601
calledName = SMBSERVER_NAME;
602                     break;
603                 }
604                 if( i < len && data[i] == '.' ) {
605                     dots++;
606                     i++;
607                 }
608             }
609         } else {
610             switch (hostName.hexCode) {
611                 case 0x1B:
612                 case 0x1C:
613                 case 0x1D:
614                     calledName = SMBSERVER_NAME;
615             }
616         }
617
618         return calledName;
619     }
620     public String JavaDoc nextCalledName() {
621
622         if( calledName == hostName.name ) {
623             calledName = SMBSERVER_NAME;
624         } else if( calledName == SMBSERVER_NAME ) {
625             NbtAddress[] addrs;
626
627             try {
628                 addrs = CLIENT.getNodeStatus( this );
629                 if( hostName.hexCode == 0x1D ) {
630                     for( int i = 0; i < addrs.length; i++ ) {
631                         if( addrs[i].hostName.hexCode == 0x20 ) {
632                             return addrs[i].hostName.name;
633                         }
634                     }
635                     return null;
636                 } else if( isDataFromNodeStatus ) {
637                     /* 'this' has been updated and should now
638                      * have a real NetBIOS name
639                      */

640                     calledName = null;
641                     return hostName.name;
642                 }
643             } catch( UnknownHostException JavaDoc uhe ) {
644                 calledName = null;
645             }
646         } else {
647             calledName = null;
648         }
649
650         return calledName;
651     }
652
653 /*
654  * There are three degrees of state that any NbtAddress can have.
655  *
656  * 1) IP Address - If a dot-quad IP string is used with getByName (or used
657  * to create an NbtAddress internal to this netbios package), no query is
658  * sent on the wire and the only state this object has is it's IP address
659  * (but that's enough to connect to a host using *SMBSERVER for CallingName).
660  *
661  * 2) IP Address, NetBIOS name, nodeType, groupName - If however a
662  * legal NetBIOS name string is used a name query request will retreive
663  * the IP, node type, and whether or not this NbtAddress represents a
664  * group name. This degree of state can be obtained with a Name Query
665  * Request or Node Status Request.
666  *
667  * 3) All - The NbtAddress will be populated with all state such as mac
668  * address, isPermanent, isBeingDeleted, ...etc. This information can only
669  * be retrieved with the Node Status request.
670  *
671  * The degree of state that an NbtAddress has is dependant on how it was
672  * created and what is required of it. The second degree of state is the
673  * most common. This is the state information that would be retrieved from
674  * WINS for example. Natrually it is not practical for every NbtAddress
675  * to be populated will all state requiring a Node Status on every host
676  * encountered. The below methods allow state to be populated when requested
677  * in a lazy fashon.
678  */

679
680     void checkData() throws UnknownHostException JavaDoc {
681         if( hostName == UNKNOWN_NAME ) {
682             getAllByAddress( this );
683         }
684     }
685     void checkNodeStatusData() throws UnknownHostException JavaDoc {
686         if( isDataFromNodeStatus == false ) {
687             getAllByAddress( this );
688         }
689     }
690
691 /**
692  * Determines if the address is a group address. This is also
693  * known as a workgroup name or group name.
694  *
695  * @throws UnknownHostException if the host cannot be resolved to find out.
696  */

697
698     public boolean isGroupAddress() throws UnknownHostException JavaDoc {
699         checkData();
700         return groupName;
701     }
702
703 /**
704  * Checks the node type of this address.
705  * @return {@link jcifs.netbios.NbtAddress#B_NODE},
706  * {@link jcifs.netbios.NbtAddress#P_NODE}, {@link jcifs.netbios.NbtAddress#M_NODE},
707  * {@link jcifs.netbios.NbtAddress#H_NODE}
708  *
709  * @throws UnknownHostException if the host cannot be resolved to find out.
710  */

711
712     public int getNodeType() throws UnknownHostException JavaDoc {
713         checkData();
714         return nodeType;
715     }
716
717 /**
718  * Determines if this address in the process of being deleted.
719  *
720  * @throws UnknownHostException if the host cannot be resolved to find out.
721  */

722
723     public boolean isBeingDeleted() throws UnknownHostException JavaDoc {
724         checkNodeStatusData();
725         return isBeingDeleted;
726     }
727
728 /**
729  * Determines if this address in conflict with another address.
730  *
731  * @throws UnknownHostException if the host cannot be resolved to find out.
732  */

733
734     public boolean isInConflict() throws UnknownHostException JavaDoc {
735         checkNodeStatusData();
736         return isInConflict;
737     }
738
739 /**
740  * Determines if this address is active.
741  *
742  * @throws UnknownHostException if the host cannot be resolved to find out.
743  */

744
745     public boolean isActive() throws UnknownHostException JavaDoc {
746         checkNodeStatusData();
747         return isActive;
748     }
749
750 /**
751  * Determines if this address is set to be permanent.
752  *
753  * @throws UnknownHostException if the host cannot be resolved to find out.
754  */

755
756     public boolean isPermanent() throws UnknownHostException JavaDoc {
757         checkNodeStatusData();
758         return isPermanent;
759     }
760
761 /**
762  * Retrieves the MAC address of the remote network interface. Samba returns all zeros.
763  *
764  * @return the MAC address as an array of six bytes
765  * @throws UnknownHostException if the host cannot be resolved to
766  * determine the MAC address.
767  */

768
769     public byte[] getMacAddress() throws UnknownHostException JavaDoc {
770         checkNodeStatusData();
771         return macAddress;
772     }
773
774 /**
775  * The hostname of this address. If the hostname is null the local machines
776  * IP address is returned.
777  *
778  * @return the text representation of the hostname associated with this address
779  */

780
781     public String JavaDoc getHostName() {
782         try {
783             checkData();
784         } catch( UnknownHostException JavaDoc uhe ) {
785             return getHostAddress();
786         }
787         return hostName.name;
788     }
789
790
791 /**
792  * Returns the raw IP address of this NbtAddress. The result is in network
793  * byte order: the highest order byte of the address is in getAddress()[0].
794  *
795  * @return a four byte array
796  */

797
798     public byte[] getAddress() {
799         byte[] addr = new byte[4];
800
801         addr[0] = (byte)(( address >>> 24 ) & 0xFF );
802         addr[1] = (byte)(( address >>> 16 ) & 0xFF );
803         addr[2] = (byte)(( address >>> 8 ) & 0xFF );
804         addr[3] = (byte)( address & 0xFF );
805         return addr;
806     }
807
808 /**
809  * To convert this address to an <code>InetAddress</code>.
810  *
811  * @return the {@link java.net.InetAddress} representation of this address.
812  */

813
814     public InetAddress JavaDoc getInetAddress() throws UnknownHostException JavaDoc {
815         return InetAddress.getByName( getHostAddress() );
816     }
817
818 /**
819  * Returns this IP adress as a {@link java.lang.String} in the form "%d.%d.%d.%d".
820  */

821
822     public String JavaDoc getHostAddress() {
823         return (( address >>> 24 ) & 0xFF ) + "." +
824             (( address >>> 16 ) & 0xFF ) + "." +
825             (( address >>> 8 ) & 0xFF ) + "." +
826             (( address >>> 0 ) & 0xFF );
827     }
828
829 /**
830  * Returned the hex code associated with this name(e.g. 0x20 is for the file service)
831  */

832
833     public int getNameType() {
834         return hostName.hexCode;
835     }
836
837 /**
838  * Returns a hashcode for this IP address. The hashcode comes from the IP address
839  * and is not generated from the string representation. So because NetBIOS nodes
840  * can have many names, all names associated with an IP will have the same
841  * hashcode.
842  */

843
844     public int hashCode() {
845         return address;
846     }
847
848 /**
849  * Determines if this address is equal two another. Only the IP Addresses
850  * are compared. Similar to the {@link #hashCode} method, the comparison
851  * is based on the integer IP address and not the string representation.
852  */

853
854     public boolean equals( Object JavaDoc obj ) {
855         return ( obj != null ) && ( obj instanceof NbtAddress ) &&
856                                         ( ((NbtAddress)obj).address == address );
857     }
858
859 /**
860  * Returns the {@link java.lang.String} representaion of this address.
861  */

862
863     public String JavaDoc toString() {
864         return hostName.toString() + "/" + getHostAddress();
865     }
866 }
867
Popular Tags