001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hdfs.security.token.block;
020
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024import java.util.EnumSet;
025
026import org.apache.hadoop.classification.InterfaceAudience;
027import org.apache.hadoop.io.Text;
028import org.apache.hadoop.io.WritableUtils;
029import org.apache.hadoop.security.UserGroupInformation;
030import org.apache.hadoop.security.token.Token;
031import org.apache.hadoop.security.token.TokenIdentifier;
032
033@InterfaceAudience.Private
034public class BlockTokenIdentifier extends TokenIdentifier {
035  static final Text KIND_NAME = new Text("HDFS_BLOCK_TOKEN");
036
037  public enum AccessMode {
038    READ, WRITE, COPY, REPLACE
039  }
040
041  private long expiryDate;
042  private int keyId;
043  private String userId;
044  private String blockPoolId;
045  private long blockId;
046  private final EnumSet<AccessMode> modes;
047
048  private byte [] cache;
049
050  public BlockTokenIdentifier() {
051    this(null, null, 0, EnumSet.noneOf(AccessMode.class));
052  }
053
054  public BlockTokenIdentifier(String userId, String bpid, long blockId,
055      EnumSet<AccessMode> modes) {
056    this.cache = null;
057    this.userId = userId;
058    this.blockPoolId = bpid;
059    this.blockId = blockId;
060    this.modes = modes == null ? EnumSet.noneOf(AccessMode.class) : modes;
061  }
062
063  @Override
064  public Text getKind() {
065    return KIND_NAME;
066  }
067
068  @Override
069  public UserGroupInformation getUser() {
070    if (userId == null || "".equals(userId)) {
071      String user = blockPoolId + ":" + Long.toString(blockId);
072      return UserGroupInformation.createRemoteUser(user);
073    }
074    return UserGroupInformation.createRemoteUser(userId);
075  }
076
077  public long getExpiryDate() {
078    return expiryDate;
079  }
080
081  public void setExpiryDate(long expiryDate) {
082    this.cache = null;
083    this.expiryDate = expiryDate;
084  }
085
086  public int getKeyId() {
087    return this.keyId;
088  }
089
090  public void setKeyId(int keyId) {
091    this.cache = null;
092    this.keyId = keyId;
093  }
094
095  public String getUserId() {
096    return userId;
097  }
098
099  public String getBlockPoolId() {
100    return blockPoolId;
101  }
102
103  public long getBlockId() {
104    return blockId;
105  }
106
107  public EnumSet<AccessMode> getAccessModes() {
108    return modes;
109  }
110
111  @Override
112  public String toString() {
113    return "block_token_identifier (expiryDate=" + this.getExpiryDate()
114        + ", keyId=" + this.getKeyId() + ", userId=" + this.getUserId()
115        + ", blockPoolId=" + this.getBlockPoolId()
116        + ", blockId=" + this.getBlockId() + ", access modes="
117        + this.getAccessModes() + ")";
118  }
119
120  static boolean isEqual(Object a, Object b) {
121    return a == null ? b == null : a.equals(b);
122  }
123
124  @Override
125  public boolean equals(Object obj) {
126    if (obj == this) {
127      return true;
128    }
129    if (obj instanceof BlockTokenIdentifier) {
130      BlockTokenIdentifier that = (BlockTokenIdentifier) obj;
131      return this.expiryDate == that.expiryDate && this.keyId == that.keyId
132          && isEqual(this.userId, that.userId)
133          && isEqual(this.blockPoolId, that.blockPoolId)
134          && this.blockId == that.blockId
135          && isEqual(this.modes, that.modes);
136    }
137    return false;
138  }
139
140  @Override
141  public int hashCode() {
142    return (int) expiryDate ^ keyId ^ (int) blockId ^ modes.hashCode()
143        ^ (userId == null ? 0 : userId.hashCode())
144        ^ (blockPoolId == null ? 0 : blockPoolId.hashCode());
145  }
146
147  @Override
148  public void readFields(DataInput in) throws IOException {
149    this.cache = null;
150    expiryDate = WritableUtils.readVLong(in);
151    keyId = WritableUtils.readVInt(in);
152    userId = WritableUtils.readString(in);
153    blockPoolId = WritableUtils.readString(in);
154    blockId = WritableUtils.readVLong(in);
155    int length = WritableUtils.readVIntInRange(in, 0,
156        AccessMode.class.getEnumConstants().length);
157    for (int i = 0; i < length; i++) {
158      modes.add(WritableUtils.readEnum(in, AccessMode.class));
159    }
160  }
161
162  @Override
163  public void write(DataOutput out) throws IOException {
164    WritableUtils.writeVLong(out, expiryDate);
165    WritableUtils.writeVInt(out, keyId);
166    WritableUtils.writeString(out, userId);
167    WritableUtils.writeString(out, blockPoolId);
168    WritableUtils.writeVLong(out, blockId);
169    WritableUtils.writeVInt(out, modes.size());
170    for (AccessMode aMode : modes) {
171      WritableUtils.writeEnum(out, aMode);
172    }
173  }
174
175  @Override
176  public byte[] getBytes() {
177    if(cache == null) cache = super.getBytes();
178
179    return cache;
180  }
181
182  @InterfaceAudience.Private
183  public static class Renewer extends Token.TrivialRenewer {
184    @Override
185    protected Text getKind() {
186      return KIND_NAME;
187    }
188  }
189}