001/* BinaryRefAddr.java -- RefAddr that uses a byte array as content.
002   Copyright (C) 2001 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010 
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.naming;
039
040import gnu.java.lang.CPStringBuilder;
041
042import java.util.Arrays;
043
044/**
045 * RefAddr that uses a byte array as content.
046 * This can be used to reference objects that can only be represented as
047 * byte arrays.
048 *
049 * @see Reference
050 * @since 1.3
051 * @author Mark Wielaard (mark@klomp.org)
052 */
053public class BinaryRefAddr extends RefAddr
054{
055  static final long serialVersionUID = -3415254970957330361L;
056        
057  /**
058   * The possibly null content of this RefAddr.
059   * Set by the constructor and returned by getContent.
060   */
061  private final byte[] buf;
062
063  /**
064   * Contructs a new BinaryRefAddr with the given type and content.
065   * The complete content of the byte array is copied to a new array.
066   */
067  public BinaryRefAddr (String addrType, byte[] buf)
068  {
069    this(addrType, buf, 0, buf.length);
070  }
071
072  /**
073   * Contructs a new BinaryRefAddr with the given type and the content
074   * taken from the given byte array.
075   * The content of the byte array is copied to a new array.
076   */
077  public BinaryRefAddr (String addrType, byte[] buf, int off, int length)
078  {
079    super(addrType);
080    this.buf = new byte[length];
081    System.arraycopy(buf, off, this.buf, 0, length);
082  }
083
084  /**
085   * Returns the byte array contents as given to the constructor.
086   * The returned byte array is shared with this object and other callers.
087   * Changing the content of the buffer is discouraged and should only be
088   * done when the byte array is locked.
089   */
090  public Object getContent ()
091  {
092    return buf;
093  }
094
095  /**
096   * Checks if the object is a BinaryRefAddr with the same type and with the
097   * same bytes in the content.
098   *
099   * @return true if the given object is an instance of BinaryRefAddr,
100   *         the addrType is the same as this addrType and the bytes of the
101   *         content are the same.
102   */
103  public boolean equals(Object o)
104  {
105    if (o instanceof BinaryRefAddr)
106      {
107        BinaryRefAddr refAddr = (BinaryRefAddr) o;
108        if (this.getType().equals(refAddr.getType()))
109        {
110          byte[] c1 = (byte[]) this.getContent();
111          byte[] c2 = (byte[]) refAddr.getContent();
112          return Arrays.equals(c1, c2);
113        }
114      }
115    return false;
116  }
117
118  /**
119   * Returns the hashCode which is the hasCode of the String returned by
120   * <code>getType()</code> plus the hashCode of the byte array returned by
121   * <code>getContent</code>. The hashCode of the byte array is calculated
122   * by taking the xor of all the bytes in the array, or zero when there are
123   * no bytes in the array.
124   */
125  public int hashCode()
126  {
127    int result = 0;
128    byte[] b = (byte[]) getContent();
129    for (int i=0; i < b.length; i++)
130      result = result^b[i];
131
132    return getType().hashCode() + result;
133  }
134
135  private static char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7',
136                               '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
137  /**
138   * Returns a String representation of the RefAddr. Only the first 32 bytes
139   * of the content are added as hex encoded characters.
140   * Should only be used for debugging purposes.
141   */
142  public String toString()
143  {
144    CPStringBuilder sb = new CPStringBuilder("[RefAddr type: ");
145    sb.append(getType());
146    sb.append(" content: 0x");
147    byte[] b = (byte[]) getContent();
148    for (int i=0; i < b.length && i < 32; i++)
149      {
150        sb.append(hex[(b[i]&0xf0)>>4]);
151        sb.append(hex[b[i]&0x0f]);
152      }
153    if (b.length > 32)
154      sb.append("...");
155    sb.append("]");
156    return sb.toString();
157  }
158}