Package com.knowgate.jcifs

Source Code of com.knowgate.jcifs.UniAddress

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

package com.knowgate.jcifs;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.IOException;
import java.util.StringTokenizer;
import com.knowgate.jcifs.netbios.NbtAddress;
import com.knowgate.jcifs.netbios.Lmhosts;

import com.knowgate.debug.*;

/**
* <p>Under normal conditions it is not necessary to use
* this class to use jCIFS properly. Name resolusion is
* handled internally to the <code>jcifs.smb</code> package.
* <p>
* This class is a wrapper for both {@link jcifs.netbios.NbtAddress}
* and {@link java.net.InetAddress}. The name resolution mechanisms
* used will systematically query all available configured resolution
* services including WINS, broadcasts, DNS, and LMHOSTS. See
* <a href="../../resolver.html">Setting Name Resolution Properties</a>
* and the <code>jcifs.resolveOrder</code> property. Changing
* jCIFS name resolution properties can greatly affect the behavior of
* the client and may be necessary for proper operation.
* <p>
* This class should be used in favor of <tt>InetAddress</tt> to resolve
* hostnames on LANs and WANs that support a mixture of NetBIOS/WINS and
* DNS resolvable hosts.
*/

public class UniAddress {

    private static final int RESOLVER_WINS    = 0;
    private static final int RESOLVER_BCAST   = 1;
    private static final int RESOLVER_DNS     = 2;
    private static final int RESOLVER_LMHOSTS = 3;

    private static int[] resolveOrder;
    private static InetAddress baddr;


    static {
        String ro = Config.getProperty( "jcifs.resolveOrder" );
        InetAddress nbns = NbtAddress.getWINSAddress();

        try {
            baddr = Config.getInetAddress( "jcifs.netbios.baddr",
                                InetAddress.getByName( "255.255.255.255" ));
        } catch( UnknownHostException uhe ) {
        }

        if( ro == null || ro.length() == 0 ) {

            /* No resolveOrder has been specified, use the
             * default which is LMHOSTS,WINS,BCAST,DNS or just
             * LMHOSTS,BCAST,DNS if jcifs.netbios.wins has not
             * been specified.
             */

            if( nbns == null ) {
                resolveOrder = new int[3];
                resolveOrder[0] = RESOLVER_LMHOSTS;
                resolveOrder[1] = RESOLVER_BCAST;
                resolveOrder[2] = RESOLVER_DNS;
            } else {
                resolveOrder = new int[4];
                resolveOrder[0] = RESOLVER_LMHOSTS;
                resolveOrder[1] = RESOLVER_WINS;
                resolveOrder[2] = RESOLVER_BCAST;
                resolveOrder[3] = RESOLVER_DNS;
            }
        } else {
            int[] tmp = new int[4];
            StringTokenizer st = new StringTokenizer( ro, "," );
            int i = 0;
            while( st.hasMoreTokens() ) {
                String s = st.nextToken().trim();
                if( s.equalsIgnoreCase( "LMHOSTS" )) {
                    tmp[i++] = RESOLVER_LMHOSTS;
                } else if( s.equalsIgnoreCase( "WINS" )) {
                    if( nbns == null ) {
                        if( DebugFile.trace ) {
                            DebugFile.writeln( "UniAddress resolveOrder specifies WINS however the " +
                                    "jcifs.netbios.wins property has not been set" );
                        }
                        continue;
                    }
                    tmp[i++] = RESOLVER_WINS;
                } else if( s.equalsIgnoreCase( "BCAST" )) {
                    tmp[i++] = RESOLVER_BCAST;
                } else if( s.equalsIgnoreCase( "DNS" )) {
                    tmp[i++] = RESOLVER_DNS;
                } else if( DebugFile.trace ) {
                    DebugFile.writeln( "unknown resolver method: " + s );
                }
            }
            resolveOrder = new int[i];
            System.arraycopy( tmp, 0, resolveOrder, 0, i );
        }
    }

    static class Sem {
        Sem( int count ) {
            this.count = count;
        }
        int count;
    }

    static class QueryThread extends Thread {

        Sem sem;
        String host, scope;
        int type;
        NbtAddress ans = null;
        InetAddress svr;
        UnknownHostException uhe;

        QueryThread( Sem sem, String host, int type,
                        String scope, InetAddress svr ) {
            super( "JCIFS-QueryThread: " + host );
            this.sem = sem;
            this.host = host;
            this.type = type;
            this.scope = scope;
            this.svr = svr;
        }
        public void run() {
            try {
                ans = NbtAddress.getByName( host, type, scope, svr );
            } catch( UnknownHostException uhe ) {
                this.uhe = uhe;
            } catch( Exception ex ) {
                this.uhe = new UnknownHostException( ex.getMessage() );
            } finally {
                synchronized( sem ) {
                    sem.count--;
                    sem.notify();
                }
            }
        }
    }

    static NbtAddress lookupServerOrWorkgroup( String name, InetAddress svr )
                                                    throws UnknownHostException {
        Sem sem = new Sem( 2 );
        int type = NbtAddress.isWINS( svr ) ? 0x1b : 0x1d;

        QueryThread q1x = new QueryThread( sem, name, type, null, svr );
        QueryThread q20 = new QueryThread( sem, name, 0x20, null, svr );
        q1x.setDaemon( true );
        q20.setDaemon( true );
        try {
            synchronized( sem ) {
                q1x.start();
                q20.start();

                while( sem.count > 0 && q1x.ans == null && q20.ans == null ) {
                    sem.wait();
                }
            }
        } catch( InterruptedException ie ) {
            throw new UnknownHostException( name );
        }
        if( q1x.ans != null ) {
            return q1x.ans;
        } else if( q20.ans != null ) {
            return q20.ans;
        } else {
            throw q1x.uhe;
        }
    }

    /**
     * Determines the address of a host given it's host name. The name can be a
     * machine name like "jcifs.samba.org",  or an IP address like "192.168.1.15".
     *
     * @param host NetBIOS or DNS hostname to resolve
     * @throws java.net.UnknownHostException if there is an error resolving the name
     */

    public static UniAddress getByName( String hostname )
                                        throws UnknownHostException {
        return getByName( hostname, false );
    }

    static boolean isDotQuadIP( String hostname ) {
        if( Character.isDigit( hostname.charAt( 0 ))) {
            int i, len, dots;
            char[] data;

            i = dots = 0;                    /* quick IP address validation */
            len = hostname.length();
            data = hostname.toCharArray();
            while( i < len && Character.isDigit( data[i++] )) {
                if( i == len && dots == 3 ) {
                    // probably an IP address
                    return true;
                }
                if( i < len && data[i] == '.' ) {
                    dots++;
                    i++;
                }
            }
        }

        return false;
    }

    static boolean isValidDnsName( String hostname ) {
        // Simple for now. Just handles "1" --> 1/0.0.0.1 kind of stuff
        return Character.isDigit( hostname.charAt( 0 )) == false;
    }

    /**
     * Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>. If the
     * <tt>possibleNTDomainOrWorkgroup</tt> parameter is <tt>true</tt> an
     * addtional name query will be performed to locate a master browser.
     */

    public static UniAddress getByName( String hostname,
                                        boolean possibleNTDomainOrWorkgroup )
                                        throws UnknownHostException {
        Object addr;
        int i;

        if( hostname == null || hostname.length() == 0 ) {
            throw new UnknownHostException();
        }

        if( isDotQuadIP( hostname )) {
            return new UniAddress( NbtAddress.getByName( hostname ));
        }

        for( i = 0; i < resolveOrder.length; i++ ) {
            try {
                switch( resolveOrder[i] ) {
                    case RESOLVER_LMHOSTS:
                        if(( addr = Lmhosts.getByName( hostname )) == null ) {
                            continue;
                        }
                        break;
                    case RESOLVER_WINS:
                        if( hostname == NbtAddress.MASTER_BROWSER_NAME ||
                                                    hostname.length() > 15 ) {
                                                    // invalid netbios name
                            continue;
                        }
                        if( possibleNTDomainOrWorkgroup ) {
                            addr = lookupServerOrWorkgroup( hostname, NbtAddress.getWINSAddress() );
                        } else {
                            addr = NbtAddress.getByName( hostname, 0x20, null, NbtAddress.getWINSAddress() );
                        }
                        break;
                    case RESOLVER_BCAST:
                        if( hostname.length() > 15 ) {
                            // invalid netbios name
                            continue;
                        }
                        if( possibleNTDomainOrWorkgroup ) {
                            addr = lookupServerOrWorkgroup( hostname, baddr );
                        } else {
                            addr = NbtAddress.getByName( hostname, 0x20, null, baddr );
                        }
                        break;
                    case RESOLVER_DNS:
                        if( isValidDnsName( hostname ) == false ) {
                            throw new UnknownHostException( hostname );
                        }
                        addr = InetAddress.getByName( hostname );
                        break;
                    default:
                        throw new UnknownHostException( hostname );
                }
                return new UniAddress( addr ); // Success
            } catch( IOException ioe ) {
                // Failure
            }
        }
        throw new UnknownHostException( hostname );
    }

    Object addr;
    String calledName;

    /**
     * Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or
     * <tt>NbtAddress</tt>.
     */

    public UniAddress( Object addr ) {
        if( addr == null ) {
            throw new IllegalArgumentException();
        }
        this.addr = addr;
    }

    /**
     * Return the IP address of this address as a 32 bit integer.
     */

    public int hashCode() {
        return addr.hashCode();
    }

    /**
     * Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal
     * if they are both <tt>UniAddress' and refer to the same IP address.
     */

    public boolean equals( Object obj ) {
        return obj instanceof UniAddress && addr.hashCode() == obj.hashCode();
    }

    /**
     * Guess first called name to try for session establishment. This
     * method is used exclusively by the <tt>jcifs.smb</tt> package.
     */

    public String firstCalledName() {
        if( addr instanceof NbtAddress ) {
            return ((NbtAddress)addr).firstCalledName();
        } else {
            calledName = ((InetAddress)addr).getHostName();
            if( isDotQuadIP( calledName )) {
                calledName = NbtAddress.SMBSERVER_NAME;
            } else {
                int i = calledName.indexOf( '.' );
                if( i > 1 && i < 15 ) {
                    calledName = calledName.substring( 0, i ).toUpperCase();
                } else if( calledName.length() > 15 ) {
                    calledName = NbtAddress.SMBSERVER_NAME;
                } else {
                    calledName = calledName.toUpperCase();
                }
            }
        }

        return calledName;
    }

    /**
     * Guess next called name to try for session establishment. This
     * method is used exclusively by the <tt>jcifs.smb</tt> package.
     */

    public String nextCalledName() {
        if( addr instanceof NbtAddress ) {
            return ((NbtAddress)addr).nextCalledName();
        } else if( calledName != NbtAddress.SMBSERVER_NAME ) {
            calledName = NbtAddress.SMBSERVER_NAME;
            return calledName;
        }
        return null;
    }

    /**
     * Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.
     */

    public Object getAddress() {
        return addr;
    }

    /**
     * Return the hostname of this address such as "MYCOMPUTER".
     */

    public String getHostName() {
        if( addr instanceof NbtAddress ) {
            return ((NbtAddress)addr).getHostName();
        }
        return ((InetAddress)addr).getHostName();
    }

    /**
     * Return the IP address as text such as "192.168.1.15".
     */

    public String getHostAddress() {
        if( addr instanceof NbtAddress ) {
            return ((NbtAddress)addr).getHostAddress();
        }
        return ((InetAddress)addr).getHostAddress();
    }

    /**
     * Return the a text representation of this address such as
     * <tt>MYCOMPUTER/192.168.1.15</tt>.
     */
    public String toString() {
        return addr.toString();
    }
}
TOP

Related Classes of com.knowgate.jcifs.UniAddress

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.