package org.maachang.util.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;

import org.maachang.util.Os;
import org.maachang.util.RunProcess;

/**
 * Ping処理.
 * 
 * @version 2008/10/28
 * @author masahito suzuki
 * @since MaachangBase 1.08
 */
public abstract class Ping {
    /**
     * Ping処理.
     * @param addr 対象のアドレスを設定します.
     * @return boolean [true]の場合、指定アドレスは存在します.
     * @exception Exception 例外.
     */
    public static final boolean check( String addr )
        throws Exception {
        if( addr == null || ( addr = addr.trim() ).length() <= 0 ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        return pingCommand( addr ) ;
    }
    
    /**
     * Ping処理.
     * @param addr 対象のアドレスを設定します.
     * @return boolean [true]の場合、指定アドレスは存在します.
     * @exception Exception 例外.
     */
    public static final boolean check( InetAddress addr )
        throws Exception {
        if( addr == null ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        return pingCommand( addr.getHostAddress() ) ;
    }
    
    /**
     * Pingコマンド実行.
     */
    private static final boolean pingCommand( String addr ) throws Exception {
        switch( Os.getInstance().getOS() ) {
            case Os.OS_WINNT :
                return pingCmdNT( addr ) ;
            case Os.OS_UNIX :
            case Os.OS_MAC_OS_X :
                return pingCmdUnix( addr ) ;
        }
        throw new IOException( "実行中のOSでは利用できません" ) ;
    }
    
    /**
     * Pingコマンド for WindowsNT.
     */
    private static final boolean pingCmdNT( String addr ) throws Exception {
        String[] cmd = new String[]{ "cmd","/c","ping -n 1 "+addr } ;
        RunProcess runProc = new RunProcess( cmd ) ;
        try {
            BufferedReader reader = new BufferedReader( new InputStreamReader( runProc.execution() ) ) ;
            int p ;
            for( ;; ) {
                String s = reader.readLine() ;
                if( s == null ) {
                    break ;
                }
                if( ( p = s.indexOf( " bytes=" ) ) != -1 && ( p = s.indexOf( " time",p ) ) != -1 &&
                    s.indexOf( " TTL=" ) != -1 ) {
                    return true ;
                }
            }
            runProc.waitFor() ;
        } finally {
            runProc.destroy() ;
        }
        return false ;
    }
    
    /**
     * Pingコマンド for Unix.
     */
    private static final boolean pingCmdUnix( String addr ) throws Exception {
        String[] cmd = new String[]{ "/bin/sh","-c","/bin/ping -n -c 1 "+addr } ;
        RunProcess runProc = new RunProcess( cmd ) ;
        try {
            BufferedReader reader = new BufferedReader( new InputStreamReader( runProc.execution() ) ) ;
            int p ;
            for( ;; ) {
                String s = reader.readLine() ;
                if( s == null ) {
                    break ;
                }
                if( ( p = s.indexOf( ": icmp_seq=" ) ) != -1 && ( p = s.indexOf( " ttl=",p ) ) != -1 &&
                    s.indexOf( " time=",p ) != -1 ) {
                    return true ;
                }
            }
            runProc.waitFor() ;
        } finally {
            runProc.destroy() ;
        }
        return false ;
    }
    
    /** test. */
    public static final void main( String[] args ) throws Exception {
        BufferedReader r = new BufferedReader( new InputStreamReader( System.in ) ) ;
        for( ;; ) {
            System.out.print( "IP>" ) ;
            String addr = r.readLine() ;
            if( addr == null ) {
                break ;
            }
            if((addr=addr.trim()).length() <= 0) {
                continue ;
            }
            System.out.println( "[" + addr + "]:" + check( addr ) ) ;
        }
    }
}
