package org.maachang.proxy.engine.conf;

import java.io.Serializable;
import java.net.InetAddress;

import org.maachang.util.NetMask;

/**
 * 禁止アドレス情報管理.
 * 
 * @version 2008/03/30
 * @author masahito suzuki
 * @since MaachangProxy 1.00
 */
public class RefusalAddressManager implements Serializable {
    /**
     * シリアルID.
     */
    private static final long serialVersionUID = 5389336480673506064L;
    
    /**
     * ネットマスク群.
     */
    private NetMask[] masks = null ;
    
    /**
     * コンストラクタ.
     */
    public RefusalAddressManager() {
        
    }
    
    /**
     * 新しいネットマスクを追加.
     * @param address 対象のIPアドレスを設定します.
     * @param mask 対象のネットマスクを設定します.
     * @exception Exception 例外.
     */
    public synchronized void add( String address,String mask )
        throws Exception {
        NetMask msk = new NetMask( address+"/"+mask ) ;
        if( masks == null ) {
            masks = new NetMask[ 1 ] ;
            masks[ 0 ] = msk ;
        }
        else {
            NetMask[] tmp = masks ;
            masks = new NetMask[ tmp.length+1 ] ;
            System.arraycopy( tmp,0,masks,0,tmp.length ) ;
            masks[ tmp.length ] = msk ;
        }
    }
    
    /**
     * 指定位置のネットマスクの内容を削除.
     * @param no 対象の項番を設定します.
     * @exception Exception 例外.
     */
    public synchronized void remove( int no ) {
        if( masks == null || no < 0 || no >= masks.length ) {
            throw new IllegalArgumentException( "指定項番["+no+"]の禁止アクセスアドレスは存在しません" ) ;
        }
        if( masks.length == 1 ) {
            masks = null ;
        }
        else {
            int len = masks.length ;
            NetMask[] tmp = new NetMask[ len-1 ] ;
            int cnt = 0 ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( i == no ) {
                    continue ;
                }
                tmp[ cnt ] = masks[ i ] ;
                cnt ++ ;
            }
            masks = tmp ;
        }
    }
    
    /**
     * 指定位置のネットマスクの内容を取得.
     * @param no 対象の項番を設定します.
     * @return NetMask 対象のネットマスクが返されます.
     * @exception Exception 例外.
     */
    public synchronized NetMask get( int no ) {
        if( masks == null || no < 0 || no >= masks.length ) {
            throw new IllegalArgumentException( "指定項番["+no+"]の禁止アクセスアドレスは存在しません" ) ;
        }
        return masks[ no ] ;
    }
    
    /**
     * 全体長を取得.
     * @return int 全体長が返されます.
     */
    public synchronized int size() {
        if( masks == null ) {
            return 0 ;
        }
        return masks.length ;
    }
    
    /**
     * 指定アドレスが一致しているかチェック.
     * @param address 対象のアドレスを設定します.
     * @return [true]の場合、禁止アドレスです.
     */
    public synchronized boolean isRefusal( InetAddress address ) {
        if( address == null ) {
            return false ;
        }
        return isRefusal( address.getHostAddress() ) ;
    }
    
    /**
     * 指定アドレスが一致しているかチェック.
     * @param address 対象のアドレスを設定します.
     * @return [true]の場合、禁止アドレスです.
     */
    public synchronized boolean isRefusal( String address ) {
        if( address == null || ( address = address.trim() ).length() <= 0 ) {
            return false ;
        }
        if( masks == null ) {
            return false ;
        }
        int len = masks.length ;
        for( int i = 0 ; i < len ; i ++ ) {
            if( masks[ i ].isRange( address ) == true ) {
                return true ;
            }
        }
        return false ;
    }
}
