Path: blob/master/src/java.base/share/classes/java/nio/file/attribute/AclEntry.java
41161 views
/*1* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.nio.file.attribute;2627import java.util.*;2829/**30* An entry in an access control list (ACL).31*32* <p> The ACL entry represented by this class is based on the ACL model33* specified in <a href="http://www.ietf.org/rfc/rfc3530.txt"><i>RFC 3530:34* Network File System (NFS) version 4 Protocol</i></a>. Each entry has four35* components as follows:36*37* <ol>38* <li><p> The {@link #type() type} component determines if the entry39* grants or denies access. </p></li>40*41* <li><p> The {@link #principal() principal} component, sometimes called the42* "who" component, is a {@link UserPrincipal} corresponding to the identity43* that the entry grants or denies access44* </p></li>45*46* <li><p> The {@link #permissions permissions} component is a set of47* {@link AclEntryPermission permissions}48* </p></li>49*50* <li><p> The {@link #flags() flags} component is a set of {@link AclEntryFlag51* flags} to indicate how entries are inherited and propagated </p></li>52* </ol>53*54* <p> ACL entries are created using an associated {@link Builder} object by55* invoking its {@link Builder#build build} method.56*57* <p> ACL entries are immutable and are safe for use by multiple concurrent58* threads.59*60* @since 1.761*/6263public final class AclEntry {6465private final AclEntryType type;66private final UserPrincipal who;67private final Set<AclEntryPermission> perms;68private final Set<AclEntryFlag> flags;6970// cached hash code71private volatile int hash;7273// private constructor74private AclEntry(AclEntryType type,75UserPrincipal who,76Set<AclEntryPermission> perms,77Set<AclEntryFlag> flags)78{79this.type = type;80this.who = who;81this.perms = perms;82this.flags = flags;83}8485/**86* A builder of {@link AclEntry} objects.87*88* <p> A {@code Builder} object is obtained by invoking one of the {@link89* AclEntry#newBuilder newBuilder} methods defined by the {@code AclEntry}90* class.91*92* <p> Builder objects are mutable and are not safe for use by multiple93* concurrent threads without appropriate synchronization.94*95* @since 1.796*/97public static final class Builder {98private AclEntryType type;99private UserPrincipal who;100private Set<AclEntryPermission> perms;101private Set<AclEntryFlag> flags;102103private Builder(AclEntryType type,104UserPrincipal who,105Set<AclEntryPermission> perms,106Set<AclEntryFlag> flags)107{108assert perms != null && flags != null;109this.type = type;110this.who = who;111this.perms = perms;112this.flags = flags;113}114115/**116* Constructs an {@link AclEntry} from the components of this builder.117* The type and who components are required to have been set in order118* to construct an {@code AclEntry}.119*120* @return a new ACL entry121*122* @throws IllegalStateException123* if the type or who component have not been set124*/125public AclEntry build() {126if (type == null)127throw new IllegalStateException("Missing type component");128if (who == null)129throw new IllegalStateException("Missing who component");130return new AclEntry(type, who, perms, flags);131}132133/**134* Sets the type component of this builder.135*136* @param type the component type137* @return this builder138*/139public Builder setType(AclEntryType type) {140if (type == null)141throw new NullPointerException();142this.type = type;143return this;144}145146/**147* Sets the principal component of this builder.148*149* @param who the principal component150* @return this builder151*/152public Builder setPrincipal(UserPrincipal who) {153if (who == null)154throw new NullPointerException();155this.who = who;156return this;157}158159// check set only contains elements of the given type160private static void checkSet(Set<?> set, Class<?> type) {161for (Object e: set) {162if (e == null)163throw new NullPointerException();164type.cast(e);165}166}167168/**169* Sets the permissions component of this builder. On return, the170* permissions component of this builder is a copy of the given set.171*172* @param perms the permissions component173* @return this builder174*175* @throws ClassCastException176* if the set contains elements that are not of type {@code177* AclEntryPermission}178*/179public Builder setPermissions(Set<AclEntryPermission> perms) {180if (perms.isEmpty()) {181// EnumSet.copyOf does not allow empty set182perms = Collections.emptySet();183} else {184// copy and check for erroneous elements185perms = EnumSet.copyOf(perms);186checkSet(perms, AclEntryPermission.class);187}188189this.perms = perms;190return this;191}192193/**194* Sets the permissions component of this builder. On return, the195* permissions component of this builder is a copy of the permissions in196* the given array.197*198* @param perms the permissions component199* @return this builder200*/201public Builder setPermissions(AclEntryPermission... perms) {202Set<AclEntryPermission> set = EnumSet.noneOf(AclEntryPermission.class);203// copy and check for null elements204for (AclEntryPermission p: perms) {205if (p == null)206throw new NullPointerException();207set.add(p);208}209this.perms = set;210return this;211}212213/**214* Sets the flags component of this builder. On return, the flags215* component of this builder is a copy of the given set.216*217* @param flags the flags component218* @return this builder219*220* @throws ClassCastException221* if the set contains elements that are not of type {@code222* AclEntryFlag}223*/224public Builder setFlags(Set<AclEntryFlag> flags) {225if (flags.isEmpty()) {226// EnumSet.copyOf does not allow empty set227flags = Collections.emptySet();228} else {229// copy and check for erroneous elements230flags = EnumSet.copyOf(flags);231checkSet(flags, AclEntryFlag.class);232}233234this.flags = flags;235return this;236}237238/**239* Sets the flags component of this builder. On return, the flags240* component of this builder is a copy of the flags in the given241* array.242*243* @param flags the flags component244* @return this builder245*/246public Builder setFlags(AclEntryFlag... flags) {247Set<AclEntryFlag> set = EnumSet.noneOf(AclEntryFlag.class);248// copy and check for null elements249for (AclEntryFlag f: flags) {250if (f == null)251throw new NullPointerException();252set.add(f);253}254this.flags = set;255return this;256}257}258259/**260* Constructs a new builder. The initial value of the type and who261* components is {@code null}. The initial value of the permissions and262* flags components is the empty set.263*264* @return a new builder265*/266public static Builder newBuilder() {267Set<AclEntryPermission> perms = Collections.emptySet();268Set<AclEntryFlag> flags = Collections.emptySet();269return new Builder(null, null, perms, flags);270}271272/**273* Constructs a new builder with the components of an existing ACL entry.274*275* @param entry an ACL entry276* @return a new builder277*/278public static Builder newBuilder(AclEntry entry) {279return new Builder(entry.type, entry.who, entry.perms, entry.flags);280}281282/**283* Returns the ACL entry type.284*285* @return the ACL entry type286*/287public AclEntryType type() {288return type;289}290291/**292* Returns the principal component.293*294* @return the principal component295*/296public UserPrincipal principal() {297return who;298}299300/**301* Returns a copy of the permissions component.302*303* <p> The returned set is a modifiable copy of the permissions.304*305* @return the permissions component306*/307public Set<AclEntryPermission> permissions() {308return new HashSet<>(perms);309}310311/**312* Returns a copy of the flags component.313*314* <p> The returned set is a modifiable copy of the flags.315*316* @return the flags component317*/318public Set<AclEntryFlag> flags() {319return new HashSet<>(flags);320}321322/**323* Compares the specified object with this ACL entry for equality.324*325* <p> If the given object is not an {@code AclEntry} then this method326* immediately returns {@code false}.327*328* <p> For two ACL entries to be considered equals requires that they are329* both the same type, their who components are equal, their permissions330* components are equal, and their flags components are equal.331*332* <p> This method satisfies the general contract of the {@link333* java.lang.Object#equals(Object) Object.equals} method. </p>334*335* @param ob the object to which this object is to be compared336*337* @return {@code true} if, and only if, the given object is an AclEntry that338* is identical to this AclEntry339*/340@Override341public boolean equals(Object ob) {342if (ob == this)343return true;344if (!(ob instanceof AclEntry other))345return false;346if (this.type != other.type)347return false;348if (!this.who.equals(other.who))349return false;350if (!this.perms.equals(other.perms))351return false;352if (!this.flags.equals(other.flags))353return false;354return true;355}356357private static int hash(int h, Object o) {358return h * 127 + o.hashCode();359}360361/**362* Returns the hash-code value for this ACL entry.363*364* <p> This method satisfies the general contract of the {@link365* Object#hashCode} method.366*/367@Override368public int hashCode() {369// return cached hash if available370if (hash != 0)371return hash;372int h = type.hashCode();373h = hash(h, who);374h = hash(h, perms);375h = hash(h, flags);376hash = h;377return hash;378}379380/**381* Returns the string representation of this ACL entry.382*383* @return the string representation of this entry384*/385@Override386public String toString() {387StringBuilder sb = new StringBuilder();388389// who390sb.append(who.getName());391sb.append(':');392393// permissions394for (AclEntryPermission perm: perms) {395sb.append(perm.name());396sb.append('/');397}398sb.setLength(sb.length()-1); // drop final slash399sb.append(':');400401// flags402if (!flags.isEmpty()) {403for (AclEntryFlag flag: flags) {404sb.append(flag.name());405sb.append('/');406}407sb.setLength(sb.length()-1); // drop final slash408sb.append(':');409}410411// type412sb.append(type.name());413return sb.toString();414}415}416417418