Java tutorial
/** * 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.fs.permission; import java.util.List; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; /** * An AclStatus contains the ACL information of a specific file. AclStatus * instances are immutable. Use a {@link Builder} to create a new instance. */ @InterfaceAudience.Public @InterfaceStability.Stable public class AclStatus { private final String owner; private final String group; private final boolean stickyBit; private final List<AclEntry> entries; private final FsPermission permission; /** * Returns the file owner. * * @return String file owner */ public String getOwner() { return owner; } /** * Returns the file group. * * @return String file group */ public String getGroup() { return group; } /** * Returns the sticky bit. * * @return boolean sticky bit */ public boolean isStickyBit() { return stickyBit; } /** * Returns the list of all ACL entries, ordered by their natural ordering. * * @return List<AclEntry> unmodifiable ordered list of all ACL entries */ public List<AclEntry> getEntries() { return entries; } /** * Returns the permission set for the path * @return {@link FsPermission} for the path */ public FsPermission getPermission() { return permission; } @Override public boolean equals(Object o) { if (o == null) { return false; } if (getClass() != o.getClass()) { return false; } AclStatus other = (AclStatus) o; return Objects.equal(owner, other.owner) && Objects.equal(group, other.group) && stickyBit == other.stickyBit && Objects.equal(entries, other.entries); } @Override public int hashCode() { return Objects.hashCode(owner, group, stickyBit, entries); } @Override public String toString() { return new StringBuilder().append("owner: ").append(owner).append(", group: ").append(group) .append(", acl: {").append("entries: ").append(entries).append(", stickyBit: ").append(stickyBit) .append('}').toString(); } /** * Builder for creating new Acl instances. */ public static class Builder { private String owner; private String group; private boolean stickyBit; private List<AclEntry> entries = Lists.newArrayList(); private FsPermission permission = null; /** * Sets the file owner. * * @param owner String file owner * @return Builder this builder, for call chaining */ public Builder owner(String owner) { this.owner = owner; return this; } /** * Sets the file group. * * @param group String file group * @return Builder this builder, for call chaining */ public Builder group(String group) { this.group = group; return this; } /** * Adds an ACL entry. * * @param e AclEntry entry to add * @return Builder this builder, for call chaining */ public Builder addEntry(AclEntry e) { this.entries.add(e); return this; } /** * Adds a list of ACL entries. * * @param entries AclEntry entries to add * @return Builder this builder, for call chaining */ public Builder addEntries(Iterable<AclEntry> entries) { for (AclEntry e : entries) this.entries.add(e); return this; } /** * Sets sticky bit. If this method is not called, then the builder assumes * false. * * @param stickyBit * boolean sticky bit * @return Builder this builder, for call chaining */ public Builder stickyBit(boolean stickyBit) { this.stickyBit = stickyBit; return this; } /** * Sets the permission for the file. * @param permission */ public Builder setPermission(FsPermission permission) { this.permission = permission; return this; } /** * Builds a new AclStatus populated with the set properties. * * @return AclStatus new AclStatus */ public AclStatus build() { return new AclStatus(owner, group, stickyBit, entries, permission); } } /** * Private constructor. * * @param file Path file associated to this ACL * @param owner String file owner * @param group String file group * @param stickyBit the sticky bit * @param entries the ACL entries * @param permission permission of the path */ private AclStatus(String owner, String group, boolean stickyBit, Iterable<AclEntry> entries, FsPermission permission) { this.owner = owner; this.group = group; this.stickyBit = stickyBit; this.entries = Lists.newArrayList(entries); this.permission = permission; } /** * Get the effective permission for the AclEntry * @param entry AclEntry to get the effective action */ public FsAction getEffectivePermission(AclEntry entry) { return getEffectivePermission(entry, permission); } /** * Get the effective permission for the AclEntry. <br> * Recommended to use this API ONLY if client communicates with the old * NameNode, needs to pass the Permission for the path to get effective * permission, else use {@link AclStatus#getEffectivePermission(AclEntry)}. * @param entry AclEntry to get the effective action * @param permArg Permission for the path. However if the client is NOT * communicating with old namenode, then this argument will not have * any preference. * @return Returns the effective permission for the entry. * @throws IllegalArgumentException If the client communicating with old * namenode and permission is not passed as an argument. */ public FsAction getEffectivePermission(AclEntry entry, FsPermission permArg) throws IllegalArgumentException { // At least one permission bits should be available. Preconditions.checkArgument(this.permission != null || permArg != null, "Permission bits are not available to calculate effective permission"); if (this.permission != null) { // permission bits from server response will have the priority for // accuracy. permArg = this.permission; } if ((entry.getName() != null || entry.getType() == AclEntryType.GROUP)) { if (entry.getScope() == AclEntryScope.ACCESS) { FsAction entryPerm = entry.getPermission(); return entryPerm.and(permArg.getGroupAction()); } else { Preconditions.checkArgument(this.entries.contains(entry) && this.entries.size() >= 3, "Passed default ACL entry not found in the list of ACLs"); // default mask entry for effective permission calculation will be the // penultimate entry. This can be mask entry in case of extended ACLs. // In case of minimal ACL, this is the owner group entry, and we end up // intersecting group FsAction with itself, which is a no-op. FsAction defaultMask = this.entries.get(this.entries.size() - 2).getPermission(); FsAction entryPerm = entry.getPermission(); return entryPerm.and(defaultMask); } } else { return entry.getPermission(); } } }