/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.tm;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.transaction.xa.Xid;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class XidImpl implements Xid, Serializable {
    private static volatile int hash = 1;

    public static final int FORMAT_ID = 0x0808;

    // ???? oracle ?????¨® Global Id ?? Branch Id ?¨´?? 64 ??????¡Á¨¦
    private byte[] globalId = new byte[Xid.MAXGTRIDSIZE];
    private byte[] branchId = new byte[Xid.MAXBQUALSIZE];

    private static String host;

    static {
        try {
            InetAddress local = InetAddress.getLocalHost();
            host = local.getHostName() + "-" + local.getHostAddress();
        }
        catch(UnknownHostException e) {
            host = "localhost-0.0.0.0";
        }
    }

    public XidImpl() {
        String xid = new StringBuffer().append(host).append("-").append(hash++).toString();
        if(xid.length() > Xid.MAXBQUALSIZE) {
            xid = xid.substring(xid.length() - Xid.MAXBQUALSIZE);
        }

        byte[] _globalId = xid.getBytes();
        if(_globalId.length > Xid.MAXGTRIDSIZE) {
            System.arraycopy(_globalId, 0, globalId, _globalId.length - Xid.MAXGTRIDSIZE, Xid.MAXGTRIDSIZE);
        }
        else {
            System.arraycopy(xid.getBytes(), 0, globalId, 0, xid.getBytes().length);
        }
    }

    private XidImpl(byte[] _globalId, byte[] _branchId) {
        if(_globalId.length > Xid.MAXGTRIDSIZE) {
            System.arraycopy(_globalId, 0, globalId, _globalId.length - Xid.MAXGTRIDSIZE, Xid.MAXGTRIDSIZE);
        }
        else {
            System.arraycopy(_globalId, 0, globalId, 0, _globalId.length);
        }
        if(_branchId.length > Xid.MAXBQUALSIZE) {
            System.arraycopy(_branchId, 0, branchId, _branchId.length - Xid.MAXBQUALSIZE, Xid.MAXBQUALSIZE);
        }
        else {
            System.arraycopy(_branchId, 0, branchId, 0, _branchId.length);
        }

    }

    public static Xid createBranchXid(Xid xid, int branchId) {
        return new XidImpl(xid.getGlobalTransactionId(), Integer.toString(branchId).getBytes());
    }

    public int getFormatId() {
        return FORMAT_ID;
    }

    public byte[] getBranchQualifier() {
        return branchId;
    }

    public byte[] getGlobalTransactionId() {
        return globalId;
    }

    public int hashCode() {
        return globalId.hashCode() + branchId.hashCode();
    }

    public String toString() {
        return new StringBuffer().append(new String(globalId).trim()).append(":").append(new String(branchId).trim()).toString();
    }

    public boolean equals(Object obj) {
        if(!(obj instanceof XidImpl)) return false;

        XidImpl xid2 = (XidImpl) obj;
        if(FORMAT_ID == xid2.getFormatId()
                && java.util.Arrays.equals(branchId, xid2.getBranchQualifier())
                && java.util.Arrays.equals(globalId, xid2.getGlobalTransactionId())) {
            return true;
        }
        else {
            return false;
        }
    }

    public static void main(String[] args) {
        Xid xid = new XidImpl();
        Xid xid1 = (XidImpl.createBranchXid(xid, 100));
        Xid xid2 = (XidImpl.createBranchXid(xid, 100));
        System.out.println(xid);
        System.out.println(xid1);
        System.out.println(xid1.equals(xid2));
    }
}

