/* $Id$ */ package ibis.ipl.impl; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; /** * This implementation of the {@link ibis.ipl.IbisIdentifier} interface * identifies an Ibis instance on the network. */ public final class IbisIdentifier implements ibis.ipl.IbisIdentifier { /** * Generated */ private static final long serialVersionUID = 3654888190542934889L; /** * The location for this Ibis instance. */ public final Location location; /** The name of the pool to which this Ibis instance belongs. */ public final String pool; /** Extra data for implementation. */ private final byte[] implementationData; /** Extra data for registry. */ private final byte[] registryData; /** Identification of Ibis instances, provided by the registry. */ private final String id; /** Application tag, provided by the application. */ private final byte[] tag; /** An Ibis identifier coded as a byte array. Computed once. */ private transient byte[] codedForm; /** * Constructs an <code>IbisIdentifier</code> with the specified parameters. * * @param id * join id, allocated by the registry. * @param implementationData * implementation-dependent data. * @param registryData * registry-dependent data. * @param location * location of this Ibis instance. * @param pool * identifies the run with the registry. * @param tag * user-provided tag for this ibis. */ public IbisIdentifier(String id, byte[] implementationData, byte[] registryData, Location location, String pool, byte[] tag) { this.id = id; this.implementationData = implementationData; this.registryData = registryData; this.location = location; this.pool = pool; this.tag = tag; this.codedForm = computeCodedForm(); } /** * Constructs an <code>IbisIdentifier</code> from the specified coded form. * * @param codedForm * the coded form. * @exception IOException * is thrown in case of trouble. */ public IbisIdentifier(byte[] codedForm) throws IOException { this(codedForm, 0, codedForm.length); } /** * Constructs an <code>IbisIdentifier</code> from the specified coded form, * at a particular offset and size. * * @param codedForm * the coded form. * @param offset * offset in the coded form. * @param size * size of the coded form. * @exception IOException * is thrown in case of trouble. */ public IbisIdentifier(byte[] codedForm, int offset, int size) throws IOException { this(new DataInputStream(new ByteArrayInputStream(codedForm, offset, size))); } /** * Reads an <code>IbisIdentifier</code> from the specified input stream. * * @param dis * the input stream. * @exception IOException * is thrown in case of trouble. */ public IbisIdentifier(DataInput dis) throws IOException { location = new Location(dis); pool = dis.readUTF(); int implementationSize = dis.readInt(); if (implementationSize < 0) { implementationData = null; } else { implementationData = new byte[implementationSize]; dis.readFully(implementationData); } int registrySize = dis.readInt(); if (registrySize < 0) { registryData = null; } else { registryData = new byte[registrySize]; dis.readFully(registryData); } id = dis.readUTF(); int tagSize = dis.readInt(); if (tagSize < 0) { tag = null; } else { tag = new byte[tagSize]; dis.readFully(tag); } codedForm = computeCodedForm(); } /** * Returns the coded form of this <code>IbisIdentifier</code>. * * @return the coded form. */ public byte[] toBytes() { if (codedForm == null) { codedForm = computeCodedForm(); } return codedForm.clone(); } private byte[] computeCodedForm() { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); location.writeTo(dos); dos.writeUTF(pool); if (implementationData == null) { dos.writeInt(-1); } else { dos.writeInt(implementationData.length); dos.write(implementationData); } if (registryData == null) { dos.writeInt(-1); } else { dos.writeInt(registryData.length); dos.write(registryData); } dos.writeUTF(id); if (tag == null) { dos.writeInt(-1); } else { dos.writeInt(tag.length); dos.write(tag); } dos.close(); return bos.toByteArray(); } catch (Exception e) { // Should not happen. return null; } } /** * Adds coded form of this <code>IbisIdentifier</code> to the specified * output stream. * * @param dos * the output stream. * @exception IOException * is thrown in case of trouble. */ public void writeTo(DataOutput dos) throws IOException { if (codedForm == null) { codedForm = computeCodedForm(); } dos.write(codedForm); } public boolean equals(Object o) { if (o == this) { return true; } if (o == null) { return false; } if (!o.getClass().equals(getClass())) { return false; } IbisIdentifier other = (IbisIdentifier) o; return other.id.equals(id) && other.pool.equals(pool); } public int hashCode() { return id.hashCode(); } public String toString() { return "(Ibis " + id + ", location " + location + ")"; } public String name() { return "Ibis " + id; } public ibis.ipl.Location location() { return location; } public String poolName() { return pool; } public byte[] tag() { return tag; } public String tagAsString() { if (tag == null) { return null; } try { return new String(tag, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("could not convert tag to string", e); } } /** * Obtains the implementation dependent data. * * @return the data. */ public byte[] getImplementationData() { return implementationData; } /** * Obtains the registry dependent data. * * @return the data. */ public byte[] getRegistryData() { return registryData; } /** * Compare to the specified Ibis identifier. * * @param c * the Ibis identifier to compare to. */ public int compareTo(ibis.ipl.IbisIdentifier c) { if (c instanceof IbisIdentifier) { // If not, the specified Ibis identifier is from a completely // different implementation. IbisIdentifier other = (IbisIdentifier) c; // First compare pools. int cmp = pool.compareTo(other.pool); if (cmp == 0) { cmp = location.compareTo(other.location); if (cmp == 0) { // Finally compare id. return id.compareTo(other.id); } } return cmp; } return this.getClass().getName().compareTo(c.getClass().getName()); } public String getID() { return id; } }