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.jclouds.s3.domain; import java.net.URI; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; /** * An Access Control List (ACL) describes the access control settings for a bucket or object in S3. * * ACL settings comprise a set of {@link Grant}s, each of which specifies a {@link Permission} that * has been granted to a specific {@link Grantee}. If an payload tries to access or modify an item * in S3, the operation will be denied unless the item has ACL settings that explicitly permit that * payload to perform that action. * * * @author James Murty * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html"/> */ public class AccessControlList { private CanonicalUser owner; private final List<Grant> grants = Lists.newArrayList(); public void setOwner(CanonicalUser owner) { this.owner = owner; } public CanonicalUser getOwner() { return owner; } /** * @return an unmodifiable set of grants represented by this ACL. */ public List<Grant> getGrants() { return Collections.unmodifiableList(grants); } /** * @return an unmodifiable set of grantees who have been assigned permissions in this ACL. */ public Set<Grantee> getGrantees() { Set<Grantee> grantees = Sets.newTreeSet(); for (Grant grant : getGrants()) { grantees.add(grant.getGrantee()); } return Collections.unmodifiableSet(grantees); } /** * Add a permission for the given grantee. * * @param grantee * @param permission */ public AccessControlList addPermission(Grantee grantee, String permission) { Grant grant = new Grant(grantee, permission); grants.add(grant); return this; } /** * Add a permission for the given group grantee. * * @param groupGranteeURI * @param permission */ public AccessControlList addPermission(URI groupGranteeURI, String permission) { return addPermission(new GroupGrantee(groupGranteeURI), permission); } /** * Revoke a permission for the given grantee, if this specific permission was granted. * * Note that you must be very explicit about the permissions you revoke, you cannot revoke * partial permissions and expect this class to determine the implied remaining permissions. For * example, if you revoke the {@link Permission#READ} permission from a grantee with * {@link Permission#FULL_CONTROL} access, <strong>the revocation will do nothing</strong> and * the grantee will retain full access. To change the access settings for this grantee, you must * first remove the {@link Permission#FULL_CONTROL} permission the add back the * {@link Permission#READ} permission. * * @param grantee * @param permission */ public AccessControlList revokePermission(Grantee grantee, String permission) { Collection<Grant> grantsForGrantee = findGrantsForGrantee(grantee.getIdentifier()); for (Grant grant : grantsForGrantee) { if (grant.getPermission().equals(permission)) { grants.remove(grant); } } return this; } /** * Revoke a permission for the given group grantee, if this specific permission was granted. * * Note that you must be very explicit about the permissions you revoke, you cannot revoke * partial permissions and expect this class to determine the implied remaining permissions. For * example, if you revoke the {@link Permission#READ} permission from a grantee with * {@link Permission#FULL_CONTROL} access, <strong>the revocation will do nothing</strong> and * the grantee will retain full access. To change the access settings for this grantee, you must * first remove the {@link Permission#FULL_CONTROL} permission the add back the * {@link Permission#READ} permission. * * @param groupGranteeURI * @param permission */ public AccessControlList revokePermission(URI groupGranteeURI, String permission) { return revokePermission(new GroupGrantee(groupGranteeURI), permission); } /** * Revoke all the permissions granted to the given grantee. * * @param grantee */ public AccessControlList revokeAllPermissions(Grantee grantee) { Collection<Grant> grantsForGrantee = findGrantsForGrantee(grantee.getIdentifier()); grants.removeAll(grantsForGrantee); return this; } /** * @param granteeId * @return the permissions assigned to a grantee, as identified by the given ID. */ public Collection<String> getPermissions(String granteeId) { Collection<Grant> grantsForGrantee = findGrantsForGrantee(granteeId); return Collections2.transform(grantsForGrantee, new Function<Grant, String>() { public String apply(Grant g) { return g.getPermission(); } }); } /** * @param grantee * @return the permissions assigned to a grantee. */ public Collection<String> getPermissions(Grantee grantee) { return getPermissions(grantee.getIdentifier()); } /** * @param granteeURI * @return the permissions assigned to a group grantee. */ public Collection<String> getPermissions(URI granteeURI) { return getPermissions(granteeURI.toASCIIString()); } /** * @param granteeId * @param permission * @return true if the grantee has the given permission. */ public boolean hasPermission(String granteeId, String permission) { return getPermissions(granteeId).contains(permission); } /** * @param grantee * @param permission * @return true if the grantee has the given permission. */ public boolean hasPermission(Grantee grantee, String permission) { return hasPermission(grantee.getIdentifier(), permission); } /** * @param granteeURI * @param permission * @return true if the grantee has the given permission. */ public boolean hasPermission(URI granteeURI, String permission) { return getPermissions(granteeURI).contains(permission); } /** * Find all the grants for a given grantee, identified by an ID which allows all Grantee types to * be searched. * * @param granteeId * identifier of a canonical user, email address user, or group. */ protected Collection<Grant> findGrantsForGrantee(final String granteeId) { return Collections2.filter(grants, new Predicate<Grant>() { public boolean apply(Grant g) { return g.getGrantee().getIdentifier().equals(granteeId); } }); } /** * Converts a canned access control policy into the equivalent access control list. * * @param cannedAP * @param ownerId */ public static AccessControlList fromCannedAccessPolicy(CannedAccessPolicy cannedAP, String ownerId) { AccessControlList acl = new AccessControlList(); acl.setOwner(new CanonicalUser(ownerId)); // Canned access policies always allow full control to the owner. acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.FULL_CONTROL); if (CannedAccessPolicy.PRIVATE == cannedAP) { // No more work to do. } else if (CannedAccessPolicy.AUTHENTICATED_READ == cannedAP) { acl.addPermission(GroupGranteeURI.AUTHENTICATED_USERS, Permission.READ); } else if (CannedAccessPolicy.PUBLIC_READ == cannedAP) { acl.addPermission(GroupGranteeURI.ALL_USERS, Permission.READ); } else if (CannedAccessPolicy.PUBLIC_READ_WRITE == cannedAP) { acl.addPermission(GroupGranteeURI.ALL_USERS, Permission.READ); acl.addPermission(GroupGranteeURI.ALL_USERS, Permission.WRITE); } return acl; } // ///////////////////////////////////////////////////////////////////////////// // Class and Enum declarations to represent Grants, Grantees and Permissions // // ///////////////////////////////////////////////////////////////////////////// public static interface Permission { public static final String READ = "READ"; public static final String WRITE = "WRITE"; public static final String READ_ACP = "READ_ACP"; public static final String WRITE_ACP = "WRITE_ACP"; public static final String FULL_CONTROL = "FULL_CONTROL"; }; public static class Grant implements Comparable<Grant> { private Grantee grantee; private final String permission; public Grant(Grantee grantee, String permission) { this.grantee = grantee; this.permission = permission; } public Grantee getGrantee() { return grantee; } @VisibleForTesting public void setGrantee(Grantee grantee) { this.grantee = grantee; } public String getPermission() { return permission; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Grant"); sb.append("{grantee=").append(grantee); sb.append(", permission=").append(permission); sb.append('}'); return sb.toString(); } public int compareTo(org.jclouds.s3.domain.AccessControlList.Grant o) { if (this == o) { return 0; } else { String myGranteeAndPermission = grantee.getIdentifier() + "\n" + permission; String otherGranteeAndPermission = o.grantee.getIdentifier() + "\n" + o.permission; return myGranteeAndPermission.compareTo(otherGranteeAndPermission); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((grantee == null) ? 0 : grantee.hashCode()); result = prime * result + ((permission == null) ? 0 : permission.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Grant other = (Grant) obj; if (grantee == null) { if (other.grantee != null) return false; } else if (!grantee.equals(other.grantee)) return false; if (permission == null) { if (other.permission != null) return false; } else if (!permission.equals(other.permission)) return false; return true; } } public abstract static class Grantee implements Comparable<Grantee> { private final String identifier; protected Grantee(String identifier) { this.identifier = identifier; } public String getIdentifier() { return identifier; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Grantee"); sb.append("{identifier='").append(identifier).append('\''); sb.append('}'); return sb.toString(); } public int compareTo(org.jclouds.s3.domain.AccessControlList.Grantee o) { return (this == o) ? 0 : getIdentifier().compareTo(o.getIdentifier()); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Grantee other = (Grantee) obj; if (identifier == null) { if (other.identifier != null) return false; } else if (!identifier.equals(other.identifier)) return false; return true; } } public static class EmailAddressGrantee extends Grantee { public EmailAddressGrantee(String emailAddress) { super(emailAddress); } public String getEmailAddress() { return getIdentifier(); } } public static class CanonicalUserGrantee extends Grantee { private final String displayName; public CanonicalUserGrantee(String id, String displayName) { super(id); this.displayName = displayName; } public CanonicalUserGrantee(String id) { this(id, null); } public String getDisplayName() { return displayName; } public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("CanonicalUserGrantee"); sb.append("{displayName='").append(displayName).append('\''); sb.append(", identifier='").append(getIdentifier()).append('\''); sb.append('}'); return sb.toString(); } } public interface GroupGranteeURI { public static final URI ALL_USERS = URI.create("http://acs.amazonaws.com/groups/global/AllUsers"); public static final URI AUTHENTICATED_USERS = URI .create("http://acs.amazonaws.com/groups/global/AuthenticatedUsers"); public static final URI LOG_DELIVERY = URI.create("http://acs.amazonaws.com/groups/s3/LogDelivery"); } public static class GroupGrantee extends Grantee { public GroupGrantee(URI groupURI) { super(groupURI.toASCIIString()); } } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("AccessControlList"); sb.append("{owner=").append(owner); sb.append(", grants=").append(grants); sb.append('}'); return sb.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((grants == null) ? 0 : grants.hashCode()); result = prime * result + ((owner == null) ? 0 : owner.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AccessControlList other = (AccessControlList) obj; if (grants == null) { if (other.grants != null) return false; } else if (!grants.equals(other.grants)) return false; if (owner == null) { if (other.owner != null) return false; } else if (!owner.equals(other.owner)) return false; return true; } }