ObjectId.java

  1. /*
  2.  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  3.  * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> and others
  4.  *
  5.  * This program and the accompanying materials are made available under the
  6.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  7.  * https://www.eclipse.org/org/documents/edl-v10.php.
  8.  *
  9.  * SPDX-License-Identifier: BSD-3-Clause
  10.  */

  11. package org.eclipse.jgit.lib;

  12. import java.io.IOException;
  13. import java.io.ObjectInputStream;
  14. import java.io.ObjectOutputStream;
  15. import java.io.Serializable;

  16. import org.eclipse.jgit.annotations.Nullable;
  17. import org.eclipse.jgit.errors.InvalidObjectIdException;
  18. import org.eclipse.jgit.util.NB;
  19. import org.eclipse.jgit.util.RawParseUtils;

  20. /**
  21.  * A SHA-1 abstraction.
  22.  */
  23. public class ObjectId extends AnyObjectId implements Serializable {
  24.     private static final long serialVersionUID = 1L;

  25.     private static final ObjectId ZEROID;

  26.     private static final String ZEROID_STR;

  27.     static {
  28.         ZEROID = new ObjectId(0, 0, 0, 0, 0);
  29.         ZEROID_STR = ZEROID.name();
  30.     }

  31.     /**
  32.      * Get the special all-null ObjectId.
  33.      *
  34.      * @return the all-null ObjectId, often used to stand-in for no object.
  35.      */
  36.     public static final ObjectId zeroId() {
  37.         return ZEROID;
  38.     }

  39.     /**
  40.      * Test a string of characters to verify it is a hex format.
  41.      * <p>
  42.      * If true the string can be parsed with {@link #fromString(String)}.
  43.      *
  44.      * @param id
  45.      *            the string to test.
  46.      * @return true if the string can converted into an ObjectId.
  47.      */
  48.     public static final boolean isId(@Nullable String id) {
  49.         if (id == null) {
  50.             return false;
  51.         }
  52.         if (id.length() != Constants.OBJECT_ID_STRING_LENGTH)
  53.             return false;
  54.         try {
  55.             for (int i = 0; i < Constants.OBJECT_ID_STRING_LENGTH; i++) {
  56.                 RawParseUtils.parseHexInt4((byte) id.charAt(i));
  57.             }
  58.             return true;
  59.         } catch (ArrayIndexOutOfBoundsException e) {
  60.             return false;
  61.         }
  62.     }

  63.     /**
  64.      * Convert an ObjectId into a hex string representation.
  65.      *
  66.      * @param i
  67.      *            the id to convert. May be null.
  68.      * @return the hex string conversion of this id's content.
  69.      */
  70.     public static final String toString(ObjectId i) {
  71.         return i != null ? i.name() : ZEROID_STR;
  72.     }

  73.     /**
  74.      * Compare two object identifier byte sequences for equality.
  75.      *
  76.      * @param firstBuffer
  77.      *            the first buffer to compare against. Must have at least 20
  78.      *            bytes from position fi through the end of the buffer.
  79.      * @param fi
  80.      *            first offset within firstBuffer to begin testing.
  81.      * @param secondBuffer
  82.      *            the second buffer to compare against. Must have at least 20
  83.      *            bytes from position si through the end of the buffer.
  84.      * @param si
  85.      *            first offset within secondBuffer to begin testing.
  86.      * @return true if the two identifiers are the same.
  87.      */
  88.     public static boolean equals(final byte[] firstBuffer, final int fi,
  89.             final byte[] secondBuffer, final int si) {
  90.         return firstBuffer[fi] == secondBuffer[si]
  91.                 && firstBuffer[fi + 1] == secondBuffer[si + 1]
  92.                 && firstBuffer[fi + 2] == secondBuffer[si + 2]
  93.                 && firstBuffer[fi + 3] == secondBuffer[si + 3]
  94.                 && firstBuffer[fi + 4] == secondBuffer[si + 4]
  95.                 && firstBuffer[fi + 5] == secondBuffer[si + 5]
  96.                 && firstBuffer[fi + 6] == secondBuffer[si + 6]
  97.                 && firstBuffer[fi + 7] == secondBuffer[si + 7]
  98.                 && firstBuffer[fi + 8] == secondBuffer[si + 8]
  99.                 && firstBuffer[fi + 9] == secondBuffer[si + 9]
  100.                 && firstBuffer[fi + 10] == secondBuffer[si + 10]
  101.                 && firstBuffer[fi + 11] == secondBuffer[si + 11]
  102.                 && firstBuffer[fi + 12] == secondBuffer[si + 12]
  103.                 && firstBuffer[fi + 13] == secondBuffer[si + 13]
  104.                 && firstBuffer[fi + 14] == secondBuffer[si + 14]
  105.                 && firstBuffer[fi + 15] == secondBuffer[si + 15]
  106.                 && firstBuffer[fi + 16] == secondBuffer[si + 16]
  107.                 && firstBuffer[fi + 17] == secondBuffer[si + 17]
  108.                 && firstBuffer[fi + 18] == secondBuffer[si + 18]
  109.                 && firstBuffer[fi + 19] == secondBuffer[si + 19];
  110.     }

  111.     /**
  112.      * Convert an ObjectId from raw binary representation.
  113.      *
  114.      * @param bs
  115.      *            the raw byte buffer to read from. At least 20 bytes must be
  116.      *            available within this byte array.
  117.      * @return the converted object id.
  118.      */
  119.     public static final ObjectId fromRaw(byte[] bs) {
  120.         return fromRaw(bs, 0);
  121.     }

  122.     /**
  123.      * Convert an ObjectId from raw binary representation.
  124.      *
  125.      * @param bs
  126.      *            the raw byte buffer to read from. At least 20 bytes after p
  127.      *            must be available within this byte array.
  128.      * @param p
  129.      *            position to read the first byte of data from.
  130.      * @return the converted object id.
  131.      */
  132.     public static final ObjectId fromRaw(byte[] bs, int p) {
  133.         final int a = NB.decodeInt32(bs, p);
  134.         final int b = NB.decodeInt32(bs, p + 4);
  135.         final int c = NB.decodeInt32(bs, p + 8);
  136.         final int d = NB.decodeInt32(bs, p + 12);
  137.         final int e = NB.decodeInt32(bs, p + 16);
  138.         return new ObjectId(a, b, c, d, e);
  139.     }

  140.     /**
  141.      * Convert an ObjectId from raw binary representation.
  142.      *
  143.      * @param is
  144.      *            the raw integers buffer to read from. At least 5 integers must
  145.      *            be available within this int array.
  146.      * @return the converted object id.
  147.      */
  148.     public static final ObjectId fromRaw(int[] is) {
  149.         return fromRaw(is, 0);
  150.     }

  151.     /**
  152.      * Convert an ObjectId from raw binary representation.
  153.      *
  154.      * @param is
  155.      *            the raw integers buffer to read from. At least 5 integers
  156.      *            after p must be available within this int array.
  157.      * @param p
  158.      *            position to read the first integer of data from.
  159.      * @return the converted object id.
  160.      */
  161.     public static final ObjectId fromRaw(int[] is, int p) {
  162.         return new ObjectId(is[p], is[p + 1], is[p + 2], is[p + 3], is[p + 4]);
  163.     }

  164.     /**
  165.      * Convert an ObjectId from hex characters (US-ASCII).
  166.      *
  167.      * @param buf
  168.      *            the US-ASCII buffer to read from. At least 40 bytes after
  169.      *            offset must be available within this byte array.
  170.      * @param offset
  171.      *            position to read the first character from.
  172.      * @return the converted object id.
  173.      */
  174.     public static final ObjectId fromString(byte[] buf, int offset) {
  175.         return fromHexString(buf, offset);
  176.     }

  177.     /**
  178.      * Convert an ObjectId from hex characters.
  179.      *
  180.      * @param str
  181.      *            the string to read from. Must be 40 characters long.
  182.      * @return the converted object id.
  183.      */
  184.     public static ObjectId fromString(String str) {
  185.         if (str.length() != Constants.OBJECT_ID_STRING_LENGTH) {
  186.             throw new InvalidObjectIdException(str);
  187.         }
  188.         return fromHexString(Constants.encodeASCII(str), 0);
  189.     }

  190.     private static final ObjectId fromHexString(byte[] bs, int p) {
  191.         try {
  192.             final int a = RawParseUtils.parseHexInt32(bs, p);
  193.             final int b = RawParseUtils.parseHexInt32(bs, p + 8);
  194.             final int c = RawParseUtils.parseHexInt32(bs, p + 16);
  195.             final int d = RawParseUtils.parseHexInt32(bs, p + 24);
  196.             final int e = RawParseUtils.parseHexInt32(bs, p + 32);
  197.             return new ObjectId(a, b, c, d, e);
  198.         } catch (ArrayIndexOutOfBoundsException e) {
  199.             InvalidObjectIdException e1 = new InvalidObjectIdException(bs, p,
  200.                     Constants.OBJECT_ID_STRING_LENGTH);
  201.             e1.initCause(e);
  202.             throw e1;
  203.         }
  204.     }

  205.     /**
  206.      * Construct an ObjectId from 160 bits provided in 5 words.
  207.      *
  208.      * @param new_1
  209.      *            an int
  210.      * @param new_2
  211.      *            an int
  212.      * @param new_3
  213.      *            an int
  214.      * @param new_4
  215.      *            an int
  216.      * @param new_5
  217.      *            an int
  218.      * @since 4.7
  219.      */
  220.     public ObjectId(int new_1, int new_2, int new_3, int new_4, int new_5) {
  221.         w1 = new_1;
  222.         w2 = new_2;
  223.         w3 = new_3;
  224.         w4 = new_4;
  225.         w5 = new_5;
  226.     }

  227.     /**
  228.      * Initialize this instance by copying another existing ObjectId.
  229.      * <p>
  230.      * This constructor is mostly useful for subclasses who want to extend an
  231.      * ObjectId with more properties, but initialize from an existing ObjectId
  232.      * instance acquired by other means.
  233.      *
  234.      * @param src
  235.      *            another already parsed ObjectId to copy the value out of.
  236.      */
  237.     protected ObjectId(AnyObjectId src) {
  238.         w1 = src.w1;
  239.         w2 = src.w2;
  240.         w3 = src.w3;
  241.         w4 = src.w4;
  242.         w5 = src.w5;
  243.     }

  244.     /** {@inheritDoc} */
  245.     @Override
  246.     public ObjectId toObjectId() {
  247.         return this;
  248.     }

  249.     private void writeObject(ObjectOutputStream os) throws IOException {
  250.         os.writeInt(w1);
  251.         os.writeInt(w2);
  252.         os.writeInt(w3);
  253.         os.writeInt(w4);
  254.         os.writeInt(w5);
  255.     }

  256.     private void readObject(ObjectInputStream ois) throws IOException {
  257.         w1 = ois.readInt();
  258.         w2 = ois.readInt();
  259.         w3 = ois.readInt();
  260.         w4 = ois.readInt();
  261.         w5 = ois.readInt();
  262.     }
  263. }