package edu.uw.zookeeper.data;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import edu.uw.zookeeper.common.AbstractPair;
import edu.uw.zookeeper.common.Reference;
import edu.uw.zookeeper.protocol.proto.Records;
public abstract class Acls {
public static enum Permission {
NONE(0),
CREATE(ZooDefs.Perms.CREATE),
READ(ZooDefs.Perms.READ),
WRITE(ZooDefs.Perms.WRITE),
DELETE(ZooDefs.Perms.DELETE),
ADMIN(ZooDefs.Perms.ADMIN);
public static Permission valueOf(int value) {
for (Permission p: Permission.values()) {
if (value == p.intValue()) {
return p;
}
}
throw new IllegalArgumentException(String.valueOf(value));
}
private final int value;
private Permission(int value) {
this.value = value;
}
public int intValue() {
return value;
}
public boolean memberOf(int flags) {
return 0 != (value & flags);
}
}
public static class PermissionSet extends ForwardingSet<Permission> {
public static PermissionSet valueOf(int flags) {
EnumSet<Permission> permissions;
if (flags == 0) {
permissions = EnumSet.of(Permission.NONE);
} else {
permissions = EnumSet.noneOf(Permission.class);
for (Permission p: Permission.values()) {
if (p.memberOf(flags)) {
permissions.add(p);
}
}
}
return of(permissions);
}
public static PermissionSet of(Permission permission) {
return of(EnumSet.of(permission));
}
public static PermissionSet of(Set<Permission> permissions) {
return new PermissionSet(permissions);
}
public static ImmutablePermissionSet immutableOf(Permission permission) {
return ImmutablePermissionSet.of(permission);
}
public static ImmutablePermissionSet immutableOf(ImmutableSet<Permission> permissions) {
return ImmutablePermissionSet.of(permissions);
}
public static final ImmutablePermissionSet ALL = immutableOf(Sets.immutableEnumSet(EnumSet.allOf(Permission.class)));
protected final Set<Permission> delegate;
protected PermissionSet(Set<Permission> delegate) {
this.delegate = delegate;
}
@Override
protected Set<Permission> delegate() {
return delegate;
}
public int intValue() {
int total = 0;
for (Permission p: this) {
total |= p.intValue();
}
return total;
}
public static class ImmutablePermissionSet extends PermissionSet {
public static ImmutablePermissionSet of(Permission permission) {
return of(ImmutableSet.of(permission));
}
public static ImmutablePermissionSet of(ImmutableSet<Permission> permissions) {
return new ImmutablePermissionSet(permissions);
}
protected final int value;
protected ImmutablePermissionSet(ImmutableSet<Permission> delegate) {
super(delegate);
this.value = super.intValue();
}
@Override
public int intValue() {
return value;
}
}
}
public static enum Scheme {
NONE, WORLD, AUTH, DIGEST, IP;
public static final Id ID_NONE = NONE.idOf("");
public static final Id ID_ANYONE = WORLD.idOf("anyone");
public static final Id ID_AUTH = AUTH.idOf("");
public static Scheme of(String value) {
for (Scheme e: Scheme.values()) {
if (value.equalsIgnoreCase(e.name())) {
return e;
}
}
return null;
}
@Override
public String toString() {
return name().toLowerCase();
}
public Id idOf(String id) {
return new Id(toString(), id);
}
}
public static class Acl extends AbstractPair<PermissionSet, Id> {
public static Acl of(PermissionSet permissions, Id id) {
return new Acl(permissions, id);
}
public static Acl fromRecord(ACL record) {
return of(PermissionSet.valueOf(record.getPerms()), record.getId());
}
public static List<Acl> fromRecordList(List<ACL> records) {
List<Acl> acl = new ArrayList<Acl>(records.size());
for (ACL e: records) {
acl.add(fromRecord(e));
}
return acl;
}
public static List<ACL> asRecordList(List<Acl> acls) {
List<ACL> records = new ArrayList<ACL>(acls.size());
for (Acl acl: acls) {
records.add(acl.toRecord());
}
return records;
}
protected Acl(PermissionSet permissions, Id id) {
super(permissions, id);
}
public PermissionSet permissions() {
return first;
}
public Id id() {
return second;
}
public ACL toRecord() {
return new ACL(permissions().intValue(), id());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", Records.toString(id())).add("permissions", permissions()).toString();
}
}
public static enum Definition implements Reference<Acl> {
NONE(Acl.of(PermissionSet.immutableOf(Permission.NONE), Scheme.ID_NONE)),
ANYONE_ALL(Acl.of(PermissionSet.ALL, Scheme.ID_ANYONE)),
ANYONE_READ(Acl.of(PermissionSet.immutableOf(Permission.READ), Scheme.ID_ANYONE)),
AUTH_ALL(Acl.of(PermissionSet.ALL, Scheme.ID_AUTH));
private Acl acl;
private List<Acl> asList;
private List<ACL> asRecord;
private Definition(Acl acl) {
this.acl = acl;
this.asList = ImmutableList.of(acl);
this.asRecord = ImmutableList.of(acl.toRecord());
}
@Override
public Acl get() {
return acl;
}
public List<Acl> asList() {
return asList;
}
public List<ACL> asRecordList() {
return asRecord;
}
}
private Acls() {}
}