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.server.namenode;
020
021import java.util.List;
022
023import org.apache.hadoop.fs.permission.AclEntry;
024import org.apache.hadoop.fs.permission.AclEntryScope;
025import org.apache.hadoop.fs.permission.AclEntryType;
026import org.apache.hadoop.fs.permission.FsAction;
027import org.apache.hadoop.hdfs.util.LongBitFormat;
028
029import com.google.common.collect.ImmutableList;
030
031/**
032 * Class to pack an AclEntry into an integer. <br>
033 * An ACL entry is represented by a 32-bit integer in Big Endian format. <br>
034 * The bits can be divided in four segments: <br>
035 * [0:1) || [1:3) || [3:6) || [6:7) || [7:32) <br>
036 * <br>
037 * [0:1) -- the scope of the entry (AclEntryScope) <br>
038 * [1:3) -- the type of the entry (AclEntryType) <br>
039 * [3:6) -- the permission of the entry (FsAction) <br>
040 * [6:7) -- A flag to indicate whether Named entry or not <br>
041 * [7:32) -- the name of the entry, which is an ID that points to a <br>
042 * string in the StringTableSection. <br>
043 */
044public enum AclEntryStatusFormat {
045
046  SCOPE(null, 1),
047  TYPE(SCOPE.BITS, 2),
048  PERMISSION(TYPE.BITS, 3),
049  NAMED_ENTRY_CHECK(PERMISSION.BITS, 1),
050  NAME(NAMED_ENTRY_CHECK.BITS, 25);
051
052  private final LongBitFormat BITS;
053
054  private AclEntryStatusFormat(LongBitFormat previous, int length) {
055    BITS = new LongBitFormat(name(), previous, length, 0);
056  }
057
058  static AclEntryScope getScope(int aclEntry) {
059    int ordinal = (int) SCOPE.BITS.retrieve(aclEntry);
060    return AclEntryScope.values()[ordinal];
061  }
062
063  static AclEntryType getType(int aclEntry) {
064    int ordinal = (int) TYPE.BITS.retrieve(aclEntry);
065    return AclEntryType.values()[ordinal];
066  }
067
068  static FsAction getPermission(int aclEntry) {
069    int ordinal = (int) PERMISSION.BITS.retrieve(aclEntry);
070    return FsAction.values()[ordinal];
071  }
072
073  static String getName(int aclEntry) {
074    int nameExists = (int) NAMED_ENTRY_CHECK.BITS.retrieve(aclEntry);
075    if (nameExists == 0) {
076      return null;
077    }
078    int id = (int) NAME.BITS.retrieve(aclEntry);
079    AclEntryType type = getType(aclEntry);
080    if (type == AclEntryType.USER) {
081      return SerialNumberManager.INSTANCE.getUser(id);
082    } else if (type == AclEntryType.GROUP) {
083      return SerialNumberManager.INSTANCE.getGroup(id);
084    }
085    return null;
086  }
087
088  static int toInt(AclEntry aclEntry) {
089    long aclEntryInt = 0;
090    aclEntryInt = SCOPE.BITS
091        .combine(aclEntry.getScope().ordinal(), aclEntryInt);
092    aclEntryInt = TYPE.BITS.combine(aclEntry.getType().ordinal(), aclEntryInt);
093    aclEntryInt = PERMISSION.BITS.combine(aclEntry.getPermission().ordinal(),
094        aclEntryInt);
095    if (aclEntry.getName() != null) {
096      aclEntryInt = NAMED_ENTRY_CHECK.BITS.combine(1, aclEntryInt);
097      if (aclEntry.getType() == AclEntryType.USER) {
098        int userId = SerialNumberManager.INSTANCE.getUserSerialNumber(aclEntry
099            .getName());
100        aclEntryInt = NAME.BITS.combine(userId, aclEntryInt);
101      } else if (aclEntry.getType() == AclEntryType.GROUP) {
102        int groupId = SerialNumberManager.INSTANCE
103            .getGroupSerialNumber(aclEntry.getName());
104        aclEntryInt = NAME.BITS.combine(groupId, aclEntryInt);
105      }
106    }
107    return (int) aclEntryInt;
108  }
109
110  static AclEntry toAclEntry(int aclEntry) {
111    AclEntry.Builder builder = new AclEntry.Builder();
112    builder.setScope(getScope(aclEntry)).setType(getType(aclEntry))
113        .setPermission(getPermission(aclEntry));
114    if (getName(aclEntry) != null) {
115      builder.setName(getName(aclEntry));
116    }
117    return builder.build();
118  }
119
120  public static int[] toInt(List<AclEntry> aclEntries) {
121    int[] entries = new int[aclEntries.size()];
122    for (int i = 0; i < entries.length; i++) {
123      entries[i] = toInt(aclEntries.get(i));
124    }
125    return entries;
126  }
127
128  public static ImmutableList<AclEntry> toAclEntries(int[] entries) {
129    ImmutableList.Builder<AclEntry> b = new ImmutableList.Builder<AclEntry>();
130    for (int entry : entries) {
131      AclEntry aclEntry = toAclEntry(entry);
132      b.add(aclEntry);
133    }
134    return b.build();
135  }
136}