/** * Copyright (C) 2009-2015 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.server.service.blob; import com.foundationdb.server.error.LobContentException; import com.foundationdb.server.types.aksql.aktypes.AkGUID; import java.util.UUID; import java.util.Arrays; public class BlobRef { public enum LeadingBitState { NO, YES, UNKNOWN } public enum LobType { SHORT_LOB, LONG_LOB, UNKNOWN } public static final byte SHORT_LOB = 0x01; public static final byte LONG_LOB = 0x02; private UUID id; private byte[] data; private byte storeTypeBit; private LeadingBitState leadingBitState = LeadingBitState.UNKNOWN; private LobType lobType = LobType.UNKNOWN; private LobType requestedType = LobType.UNKNOWN; private Boolean returnedBlobInUnwrappedMode = false; public BlobRef(byte[] value) { this(value, LeadingBitState.UNKNOWN); } public BlobRef(byte[] value, LeadingBitState state) { this(value, state, LobType.UNKNOWN, LobType.UNKNOWN); } public BlobRef(byte[] value, LeadingBitState state, LobType definedType, LobType requestedType) { this.leadingBitState = state; this.lobType = definedType; this.requestedType = requestedType; if (leadingBitState == LeadingBitState.YES) { storeTypeBit = value[0]; if (storeTypeBit == SHORT_LOB) { lobType = LobType.SHORT_LOB; } else if (storeTypeBit == LONG_LOB) { lobType = LobType.LONG_LOB; } else { throw new LobContentException("Invalid leading bit -"); } if (isShortLob()) { data = Arrays.copyOfRange(value, 1, value.length); } else if (isLongLob()) { if (value.length != 17){ throw new LobContentException("invalid id length"); } id = AkGUID.bytesToUUID(value, 1); } else { throw new LobContentException("Invalid store type"); } } else { data = value; } } public byte[] getValue() { // always returns data with the correct leading bit if applicable byte[] res; if (leadingBitState == LeadingBitState.YES) { if (isShortLob()) { res = new byte[data.length + 1]; System.arraycopy(data, 0, res, 1, data.length); res[0] = storeTypeBit; } else { res = new byte[17]; System.arraycopy(AkGUID.uuidToBytes(id), 0, res, 1, 16); res[0] = storeTypeBit; } } else { res = data; } return res; } public boolean isShortLob() { return lobType == LobType.SHORT_LOB; } public boolean isLongLob() { return lobType == LobType.LONG_LOB; } public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } public byte[] getBytes() { return data; } public LobType getLobType() { return lobType; } public void setLobType(LobType lobType) { this.lobType = lobType; } public LobType getRequestedLobType() { return requestedType; } public Boolean isReturnedBlobInUnwrappedMode() { return returnedBlobInUnwrappedMode; } public void setIsReturnedBlobInUnwrappedMode(Boolean value) { returnedBlobInUnwrappedMode = value; } }