| | |
| | | import java.util.TreeSet; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteSequence; |
| | | import org.forgerock.opendj.ldap.ByteSequenceReader; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.opends.server.types.DN; |
| | |
| | | public static final byte TAG_DIRECTORY_SERVER_ENTRY = 0x61; |
| | | |
| | | /** |
| | | * Decode a long from a byte array, starting at start index and ending at end |
| | | * index. |
| | | * |
| | | * @param bytes |
| | | * The bytes value of the long. |
| | | * @param start |
| | | * the array index where to start computing the long |
| | | * @param end |
| | | * the array index exclusive where to end computing the long |
| | | * @return the long representation of the read bytes. |
| | | * @throws ArrayIndexOutOfBoundsException |
| | | * if the bytes array length is less than end. |
| | | */ |
| | | public static long toLong(byte[] bytes, int start, int end) |
| | | throws ArrayIndexOutOfBoundsException |
| | | { |
| | | long v = 0; |
| | | for (int i = start; i < end; i++) |
| | | { |
| | | v <<= 8; |
| | | v |= (bytes[i] & 0xFF); |
| | | } |
| | | return v; |
| | | } |
| | | |
| | | /** |
| | | * Decode an entry ID count from its database representation. |
| | | * |
| | | * @param bytes The database value of the entry ID count. |
| | | * @return The entry ID count. |
| | | * Cannot be negative if encoded with #entryIDUndefinedSizeToDatabase(long) |
| | | * @see #entryIDUndefinedSizeToDatabase(long) |
| | | */ |
| | | public static long entryIDUndefinedSizeFromDatabase(byte[] bytes) |
| | | { |
| | | if(bytes == null) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | if(bytes.length == 8) |
| | | { |
| | | long v = 0; |
| | | v |= (bytes[0] & 0x7F); |
| | | for (int i = 1; i < 8; i++) |
| | | { |
| | | v <<= 8; |
| | | v |= (bytes[i] & 0xFF); |
| | | } |
| | | return v; |
| | | } |
| | | return Long.MAX_VALUE; |
| | | } |
| | | |
| | | /** |
| | | * Decode an array of entry ID values from its database representation. |
| | | * |
| | | * @param bytes The raw database value, null if there is no value and |
| | | * hence no entry IDs. Note that this method will throw an |
| | | * ArrayIndexOutOfBoundsException if the bytes array length is |
| | | * not a multiple of 8. |
| | | * @return An array of entry ID values. |
| | | * @see #entryIDListToDatabase(long[]) |
| | | */ |
| | | public static long[] entryIDListFromDatabase(ByteSequence bytes) |
| | | { |
| | | final ByteSequenceReader r = bytes.asReader(); |
| | | |
| | | final int count = bytes.length() / 8; |
| | | final long[] entryIDList = new long[count]; |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | entryIDList[i] = r.getLong(); |
| | | } |
| | | return entryIDList; |
| | | } |
| | | |
| | | /** |
| | | * Decode a integer array using the specified byte array read from DB. |
| | | * |
| | | * @param bytes The byte array. |
| | | * @return An integer array. |
| | | */ |
| | | public static int[] intArrayFromDatabaseBytes(byte[] bytes) { |
| | | byte[] decodedBytes = bytes; |
| | | |
| | | int count = decodedBytes.length / 8; |
| | | int[] entryIDList = new int[count]; |
| | | for (int pos = 0, i = 0; i < count; i++) { |
| | | int v = 0; |
| | | pos +=4; |
| | | v |= (decodedBytes[pos++] & 0xFFL) << 24; |
| | | v |= (decodedBytes[pos++] & 0xFFL) << 16; |
| | | v |= (decodedBytes[pos++] & 0xFFL) << 8; |
| | | v |= (decodedBytes[pos++] & 0xFFL); |
| | | entryIDList[i] = v; |
| | | } |
| | | |
| | | return entryIDList; |
| | | } |
| | | |
| | | /** |
| | | * Encode an entry ID set count to its database representation. |
| | | * |
| | | * @param count The entry ID set count to be encoded. |
| | | * @return The encoded database value of the entry ID set count. |
| | | * @see #entryIDUndefinedSizeFromDatabase(byte[]) |
| | | */ |
| | | public static byte[] entryIDUndefinedSizeToDatabase(long count) |
| | | { |
| | | byte[] bytes = new byte[8]; |
| | | long v = count; |
| | | for (int i = 7; i >= 1; i--) |
| | | { |
| | | bytes[i] = (byte) (v & 0xFF); |
| | | v >>>= 8; |
| | | } |
| | | bytes[0] = (byte) ((v | 0x80) & 0xFF); |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * Encode an array of entry ID values to its database representation. |
| | | * |
| | | * @param entryIDArray An array of entry ID values. |
| | | * @return The encoded database value. |
| | | */ |
| | | public static byte[] entryIDListToDatabase(long[] entryIDArray) |
| | | { |
| | | if (entryIDArray.length == 0) |
| | | { |
| | | // Zero values |
| | | return null; |
| | | } |
| | | |
| | | byte[] bytes = new byte[8*entryIDArray.length]; |
| | | for (int pos = 0, i = 0; i < entryIDArray.length; i++) |
| | | { |
| | | long v = entryIDArray[i]; |
| | | bytes[pos++] = (byte) ((v >>> 56) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 48) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 40) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 32) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 24) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 16) & 0xFF); |
| | | bytes[pos++] = (byte) ((v >>> 8) & 0xFF); |
| | | bytes[pos++] = (byte) (v & 0xFF); |
| | | } |
| | | |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * Decode a DN value from its database key representation. |
| | | * |
| | | * @param dnKey The database key value of the DN. |
| | |
| | | return dn; |
| | | } |
| | | |
| | | /** |
| | | * Find the length of bytes that represents the superior DN of the given |
| | | * DN key. The superior DN is represented by the initial bytes of the DN key. |
| | | * |
| | | * @param dnKey The database key value of the DN. |
| | | * @param offset Starting position in the database key data. |
| | | * @param length The length of the database key data. |
| | | * @return The length of the superior DN or -1 if the given dn is the |
| | | * root DN or 0 if the superior DN is removed. |
| | | */ |
| | | public static int findDNKeyParent(byte[] dnKey, int offset, int length) |
| | | { |
| | | if(length == 0) |
| | | { |
| | | // This is the root or base DN |
| | | return -1; |
| | | } |
| | | |
| | | // We will walk backwards through the buffer and find the first unescaped comma |
| | | for(int i = offset+length - 1; i >= offset; i--) |
| | | { |
| | | if(dnKey[i] == 0x00 && i-1 >= offset && dnKey[i-1] != 0x5C) |
| | | { |
| | | return i; |
| | | } |
| | | } |
| | | return offset; |
| | | } |
| | | |
| | | public static int findDNKeyParent(ByteSequence dnKey) |
| | | { |
| | | if (dnKey.length() == 0) |