Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdfs.security.token.block;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Optional;
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.AccessModeProto;
import org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.BlockTokenSecretProto;
import org.apache.hadoop.hdfs.protocolPB.PBHelperClient;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
@InterfaceAudience.Private
public class BlockTokenIdentifier extends TokenIdentifier {
static final Text KIND_NAME = new Text("HDFS_BLOCK_TOKEN");
public enum AccessMode {
READ, WRITE, COPY, REPLACE
}
private long expiryDate;
private int keyId;
private String userId;
private String blockPoolId;
private long blockId;
private final EnumSet modes;
private StorageType[] storageTypes;
private String[] storageIds;
private boolean useProto;
private byte [] cache;
public BlockTokenIdentifier() {
this(null, null, 0, EnumSet.noneOf(AccessMode.class), null, null,
false);
}
public BlockTokenIdentifier(String userId, String bpid, long blockId,
EnumSet modes, StorageType[] storageTypes,
String[] storageIds, boolean useProto) {
this.cache = null;
this.userId = userId;
this.blockPoolId = bpid;
this.blockId = blockId;
this.modes = modes == null ? EnumSet.noneOf(AccessMode.class) : modes;
this.storageTypes = Optional.ofNullable(storageTypes)
.orElse(StorageType.EMPTY_ARRAY);
this.storageIds = Optional.ofNullable(storageIds)
.orElse(new String[0]);
this.useProto = useProto;
}
@Override
public Text getKind() {
return KIND_NAME;
}
@Override
public UserGroupInformation getUser() {
if (userId == null || "".equals(userId)) {
String user = blockPoolId + ":" + Long.toString(blockId);
return UserGroupInformation.createRemoteUser(user);
}
return UserGroupInformation.createRemoteUser(userId);
}
public long getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(long expiryDate) {
this.cache = null;
this.expiryDate = expiryDate;
}
public int getKeyId() {
return this.keyId;
}
public void setKeyId(int keyId) {
this.cache = null;
this.keyId = keyId;
}
public String getUserId() {
return userId;
}
public String getBlockPoolId() {
return blockPoolId;
}
public long getBlockId() {
return blockId;
}
public EnumSet getAccessModes() {
return modes;
}
public StorageType[] getStorageTypes(){
return storageTypes;
}
public String[] getStorageIds(){
return storageIds;
}
@Override
public String toString() {
return "block_token_identifier (expiryDate=" + this.getExpiryDate()
+ ", keyId=" + this.getKeyId() + ", userId=" + this.getUserId()
+ ", blockPoolId=" + this.getBlockPoolId()
+ ", blockId=" + this.getBlockId() + ", access modes="
+ this.getAccessModes() + ", storageTypes= "
+ Arrays.toString(this.getStorageTypes()) + ", storageIds= "
+ Arrays.toString(this.getStorageIds()) + ")";
}
static boolean isEqual(Object a, Object b) {
return a == null ? b == null : a.equals(b);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof BlockTokenIdentifier) {
BlockTokenIdentifier that = (BlockTokenIdentifier) obj;
return this.expiryDate == that.expiryDate && this.keyId == that.keyId
&& isEqual(this.userId, that.userId)
&& isEqual(this.blockPoolId, that.blockPoolId)
&& this.blockId == that.blockId
&& isEqual(this.modes, that.modes)
&& Arrays.equals(this.storageTypes, that.storageTypes)
&& Arrays.equals(this.storageIds, that.storageIds);
}
return false;
}
@Override
public int hashCode() {
return (int) expiryDate ^ keyId ^ (int) blockId ^ modes.hashCode()
^ (userId == null ? 0 : userId.hashCode())
^ (blockPoolId == null ? 0 : blockPoolId.hashCode())
^ (storageTypes == null ? 0 : Arrays.hashCode(storageTypes))
^ (storageIds == null ? 0 : Arrays.hashCode(storageIds));
}
/**
* readFields peeks at the first byte of the DataInput and determines if it
* was written using WritableUtils ("Legacy") or Protobuf. We can do this
* because we know the first field is the Expiry date.
*
* In the case of the legacy buffer, the expiry date is a VInt, so the size
* (which should always be >1) is encoded in the first byte - which is
* always negative due to this encoding. However, there are sometimes null
* BlockTokenIdentifier written so we also need to handle the case there
* the first byte is also 0.
*
* In the case of protobuf, the first byte is a type tag for the expiry date
* which is written as field_number << 3 | wire_type.
* So as long as the field_number is less than 16, but also positive, then
* we know we have a Protobuf.
*
* @param in DataInput to deserialize this object from.
* @throws IOException
*/
@Override
public void readFields(DataInput in) throws IOException {
this.cache = null;
final DataInputStream dis = (DataInputStream)in;
if (!dis.markSupported()) {
throw new IOException("Could not peek first byte.");
}
dis.mark(1);
final byte firstByte = dis.readByte();
dis.reset();
if (firstByte <= 0) {
readFieldsLegacy(dis);
} else {
readFieldsProtobuf(dis);
}
}
@VisibleForTesting
void readFieldsLegacy(DataInput in) throws IOException {
expiryDate = WritableUtils.readVLong(in);
keyId = WritableUtils.readVInt(in);
userId = WritableUtils.readString(in);
blockPoolId = WritableUtils.readString(in);
blockId = WritableUtils.readVLong(in);
int length = WritableUtils.readVIntInRange(in, 0,
AccessMode.class.getEnumConstants().length);
for (int i = 0; i < length; i++) {
modes.add(WritableUtils.readEnum(in, AccessMode.class));
}
length = WritableUtils.readVInt(in);
StorageType[] readStorageTypes = new StorageType[length];
for (int i = 0; i < length; i++) {
readStorageTypes[i] = WritableUtils.readEnum(in, StorageType.class);
}
storageTypes = readStorageTypes;
length = WritableUtils.readVInt(in);
String[] readStorageIds = new String[length];
for (int i = 0; i < length; i++) {
readStorageIds[i] = WritableUtils.readString(in);
}
storageIds = readStorageIds;
useProto = false;
}
@VisibleForTesting
void readFieldsProtobuf(DataInput in) throws IOException {
BlockTokenSecretProto blockTokenSecretProto =
BlockTokenSecretProto.parseFrom((DataInputStream)in);
expiryDate = blockTokenSecretProto.getExpiryDate();
keyId = blockTokenSecretProto.getKeyId();
if (blockTokenSecretProto.hasUserId()) {
userId = blockTokenSecretProto.getUserId();
} else {
userId = null;
}
if (blockTokenSecretProto.hasBlockPoolId()) {
blockPoolId = blockTokenSecretProto.getBlockPoolId();
} else {
blockPoolId = null;
}
blockId = blockTokenSecretProto.getBlockId();
for (int i = 0; i < blockTokenSecretProto.getModesCount(); i++) {
AccessModeProto accessModeProto = blockTokenSecretProto.getModes(i);
modes.add(PBHelperClient.convert(accessModeProto));
}
storageTypes = blockTokenSecretProto.getStorageTypesList().stream()
.map(PBHelperClient::convertStorageType)
.toArray(StorageType[]::new);
storageIds = blockTokenSecretProto.getStorageIdsList().stream()
.toArray(String[]::new);
useProto = true;
}
@Override
public void write(DataOutput out) throws IOException {
if (useProto) {
writeProtobuf(out);
} else {
writeLegacy(out);
}
}
@VisibleForTesting
void writeLegacy(DataOutput out) throws IOException {
WritableUtils.writeVLong(out, expiryDate);
WritableUtils.writeVInt(out, keyId);
WritableUtils.writeString(out, userId);
WritableUtils.writeString(out, blockPoolId);
WritableUtils.writeVLong(out, blockId);
WritableUtils.writeVInt(out, modes.size());
for (AccessMode aMode : modes) {
WritableUtils.writeEnum(out, aMode);
}
WritableUtils.writeVInt(out, storageTypes.length);
for (StorageType type: storageTypes){
WritableUtils.writeEnum(out, type);
}
WritableUtils.writeVInt(out, storageIds.length);
for (String id: storageIds) {
WritableUtils.writeString(out, id);
}
}
@VisibleForTesting
void writeProtobuf(DataOutput out) throws IOException {
BlockTokenSecretProto secret = PBHelperClient.convert(this);
out.write(secret.toByteArray());
}
@Override
public byte[] getBytes() {
if(cache == null) cache = super.getBytes();
return cache;
}
@InterfaceAudience.Private
public static class Renewer extends Token.TrivialRenewer {
@Override
protected Text getKind() {
return KIND_NAME;
}
}
}