package org.maachang.util.net;

import java.util.List;

import org.maachang.util.StringUtil;

/**
 * ネットワークアドレス取得Linux版. <BR>
 * <BR>
 * Linux版のネットワークアドレス取得処理です.
 * 
 * @version 2008/10/28
 * @author masahito suzuki
 * @since MaachangBase 1.08
 */
class NetAdapterByLinux extends AbstractNetAdapter {
    /**
     * IPアドレス取得コマンド.
     */
    private static final String IPCONFIG_COMMAND = "ifconfig";

    /**
     * 媒体開始文字.
     */
    private static final String ADAPTER_NAME_1 = "link";
    private static final String ADAPTER_NAME_2 = "encap:";

    /**
     * IPアドレス区切り値.
     */
    private static final char DIV_IP_CODE = '.';

    /**
     * macアドレス区切り値.
     */
    private static final char DIV_MAC_CODE = ':';

    /**
     * IPアドレス.
     */
    private static final String IP_ADDR = "inet addr:";

    /**
     * サブネットマスク.
     */
    private static final String SUB_NET = "mask";

    /**
     * macアドレス.
     */
    private static final String MAC_ADDR = "hwaddr";

    /**
     * コンストラクタ.
     */
    public NetAdapterByLinux() {
        init();
    }

    /**
     * ネットワーク情報取得処理.
     * 
     * @exception Exception
     *                例外.
     */
    public void load() throws Exception {
        int i, j;
        int len;
        int lenJ;
        int pnt;
        int off;
        int st, et;
        int localCheck;
        char code;
        List<String> cmdOut = null;
        String name = null;
        String value = null;

        try {

            this.clear();
            cmdOut = super.runExec(NetAdapterByLinux.IPCONFIG_COMMAND);

            len = cmdOut.size();
            for (i = 0, localCheck = 0; i < len; i++) {

                String bcmd = cmdOut.get(i);
                String cmd = bcmd.toLowerCase() ;
                // adapter名を取得.
                if ((off = cmd.indexOf(NetAdapterByLinux.ADAPTER_NAME_1)) != -1
                        && cmd.indexOf(NetAdapterByLinux.ADAPTER_NAME_2, off) != -1) {

                    pnt = off;

                    name = StringUtil.trim(bcmd.substring(0, pnt));

                }

                // IPアドレスの場合.
                if ((pnt = cmd.indexOf(NetAdapterByLinux.IP_ADDR)) != -1 ){
                    pnt = pnt + NetAdapterByLinux.IP_ADDR.length();
                    lenJ = cmd.length();

                    for (j = pnt, st = -1, et = -1; j < lenJ; j++) {

                        code = cmd.charAt(j);

                        if (st == -1) {
                            if (code >= '0' && code <= '9') {
                                st = j;
                            }
                        } else if (code == NetAdapterByLinux.DIV_IP_CODE
                                || (code >= '0' && code <= '9')) {
                            et = j;
                        } else {
                            break;
                        }

                    }
                    value = StringUtil.trim(bcmd.substring(st, et + 1));

                    // 対象IPアドレスがローカルアドレスを示す場合.
                    if (value.equals(LOCAL_IP) == true) {
                        localCheck++;
                    }

                    super.setIpAddress(name, value);
                }

                // サブネットマスクの場合.
                if ((pnt = cmd.indexOf(NetAdapterByLinux.SUB_NET)) != -1) {
                    pnt = pnt + NetAdapterByLinux.SUB_NET.length();
                    lenJ = cmd.length();

                    for (j = pnt, st = -1, et = -1; j < lenJ; j++) {

                        code = cmd.charAt(j);

                        if (st == -1) {
                            if (code >= '0' && code <= '9') {
                                st = j;
                            }
                        } else if (code == NetAdapterByLinux.DIV_IP_CODE
                                || (code >= '0' && code <= '9')) {
                            et = j;
                        } else {
                            break;
                        }

                    }

                    value = StringUtil.trim(bcmd.substring(st, et + 1));
                    super.setSubnetMask(name, value);
                }

                // MACアドレスの場合.
                if ((pnt = cmd.indexOf(NetAdapterByLinux.MAC_ADDR)) != -1) {
                    pnt = pnt + NetAdapterByLinux.MAC_ADDR.length();
                    lenJ = cmd.length();

                    for (j = pnt, st = -1, et = -1; j < lenJ; j++) {

                        code = cmd.charAt(j);

                        if (st == -1) {
                            if ((code >= '0' && code <= '9')
                                    || (code >= 'a' && code <= 'f')) {
                                st = j;
                            }
                        } else if (code == NetAdapterByLinux.DIV_MAC_CODE
                                || (code >= '0' && code <= '9')
                                || (code >= 'a' && code <= 'f')) {
                            et = j;
                        } else {
                            break;
                        }

                    }

                    value = StringUtil.trim(bcmd.substring(st, et + 1))
                            .toUpperCase();
                    super.setMacAddress(name, value);
                }

            }

            // ローカルアドレスが存在しない場合.
            if (localCheck == 0) {
                // アドレスを追加.
                super.setIpAddress(AbstractNetAdapter.DEFAULT_ETHER_NAME, LOCAL_IP);
                // ホスト名を追加.
                super.setSubnetMask(AbstractNetAdapter.DEFAULT_ETHER_NAME,
                        AbstractNetAdapter.LO_HOST_SUB);
            }

        } catch (Exception e) {
            this.clear();
            throw e;
        } finally {
            cmdOut = null;
            name = null;
            value = null;
        }

    }

}
