AclTransformation { public static List<AclEntry> mergeAclEntries(List<AclEntry> existingAcl, List<AclEntry> inAclSpec) throws AclException { ValidatedAclSpec aclSpec = new ValidatedAclSpec(inAclSpec); ArrayList<AclEntry> aclBuilder = Lists.newArrayListWithCapacity(MAX_ENTRIES); List<AclEntry> foundAclSpecEntries = Lists.newArrayListWithCapacity(MAX_ENTRIES); EnumMap<AclEntryScope, AclEntry> providedMask = Maps.newEnumMap(AclEntryScope.class); EnumSet<AclEntryScope> maskDirty = EnumSet.noneOf(AclEntryScope.class); EnumSet<AclEntryScope> scopeDirty = EnumSet.noneOf(AclEntryScope.class); for (AclEntry existingEntry: existingAcl) { AclEntry aclSpecEntry = aclSpec.findByKey(existingEntry); if (aclSpecEntry != null) { foundAclSpecEntries.add(aclSpecEntry); scopeDirty.add(aclSpecEntry.getScope()); if (aclSpecEntry.getType() == MASK) { providedMask.put(aclSpecEntry.getScope(), aclSpecEntry); maskDirty.add(aclSpecEntry.getScope()); } else { aclBuilder.add(aclSpecEntry); } } else { if (existingEntry.getType() == MASK) { providedMask.put(existingEntry.getScope(), existingEntry); } else { aclBuilder.add(existingEntry); } } } for (AclEntry newEntry: aclSpec) { if (Collections.binarySearch(foundAclSpecEntries, newEntry, ACL_ENTRY_COMPARATOR) < 0) { scopeDirty.add(newEntry.getScope()); if (newEntry.getType() == MASK) { providedMask.put(newEntry.getScope(), newEntry); maskDirty.add(newEntry.getScope()); } else { aclBuilder.add(newEntry); } } } copyDefaultsIfNeeded(aclBuilder); calculateMasks(aclBuilder, providedMask, maskDirty, scopeDirty); return buildAndValidateAcl(aclBuilder); } private  AclTransformation(); static List<AclEntry> filterAclEntriesByAclSpec(
      List<AclEntry> existingAcl, List<AclEntry> inAclSpec); static List<AclEntry> filterDefaultAclEntries(
      List<AclEntry> existingAcl); static List<AclEntry> mergeAclEntries(List<AclEntry> existingAcl,
      List<AclEntry> inAclSpec); static List<AclEntry> replaceAclEntries(List<AclEntry> existingAcl,
      List<AclEntry> inAclSpec);  }
@Test(expected=AclException.class) public void testMergeAclDefaultEntriesInputTooLarge() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); mergeAclEntries(existing, ACL_SPEC_DEFAULT_TOO_LARGE); }
@Test(expected = AclException.class) public void testMergeAclDefaultEntriesResultTooLarge() throws AclException { ImmutableList.Builder<AclEntry> aclBuilder = new ImmutableList.Builder<AclEntry>() .add(aclEntry(DEFAULT, USER, ALL)); for (int i = 1; i <= 28; ++i) { aclBuilder.add(aclEntry(DEFAULT, USER, "user" + i, READ)); } aclBuilder .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ)) .add(aclEntry(DEFAULT, OTHER, NONE)); List<AclEntry> existing = aclBuilder.build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, "bruce", READ)); mergeAclEntries(existing, aclSpec); }
@Test public void testMergeAclEntries() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ_EXECUTE)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", ALL)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", ALL)) .add(aclEntry(ACCESS, GROUP, READ_EXECUTE)) .add(aclEntry(ACCESS, MASK, ALL)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesUnchanged() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", ALL)) .add(aclEntry(ACCESS, GROUP, READ_EXECUTE)) .add(aclEntry(ACCESS, GROUP, "sales", ALL)) .add(aclEntry(ACCESS, MASK, ALL)) .add(aclEntry(ACCESS, OTHER, NONE)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", ALL)) .add(aclEntry(DEFAULT, GROUP, READ_EXECUTE)) .add(aclEntry(DEFAULT, GROUP, "sales", ALL)) .add(aclEntry(DEFAULT, MASK, ALL)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, ALL), aclEntry(ACCESS, USER, "bruce", ALL), aclEntry(ACCESS, GROUP, READ_EXECUTE), aclEntry(ACCESS, GROUP, "sales", ALL), aclEntry(ACCESS, MASK, ALL), aclEntry(ACCESS, OTHER, NONE), aclEntry(DEFAULT, USER, ALL), aclEntry(DEFAULT, USER, "bruce", ALL), aclEntry(DEFAULT, GROUP, READ_EXECUTE), aclEntry(DEFAULT, GROUP, "sales", ALL), aclEntry(DEFAULT, MASK, ALL), aclEntry(DEFAULT, OTHER, NONE)); assertEquals(existing, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesMultipleNewBeforeExisting() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "diana", READ)) .add(aclEntry(ACCESS, GROUP, READ_EXECUTE)) .add(aclEntry(ACCESS, MASK, READ_EXECUTE)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", READ_EXECUTE), aclEntry(ACCESS, USER, "clark", READ_EXECUTE), aclEntry(ACCESS, USER, "diana", READ_EXECUTE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ_EXECUTE)) .add(aclEntry(ACCESS, USER, "clark", READ_EXECUTE)) .add(aclEntry(ACCESS, USER, "diana", READ_EXECUTE)) .add(aclEntry(ACCESS, GROUP, READ_EXECUTE)) .add(aclEntry(ACCESS, MASK, READ_EXECUTE)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesAccessMaskCalculated() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", READ_EXECUTE), aclEntry(ACCESS, USER, "diana", READ)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ_EXECUTE)) .add(aclEntry(ACCESS, USER, "diana", READ)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ_EXECUTE)) .add(aclEntry(ACCESS, OTHER, READ)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesDefaultMaskCalculated() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", READ)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, "bruce", READ_WRITE), aclEntry(DEFAULT, USER, "diana", READ_EXECUTE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", READ_WRITE)) .add(aclEntry(DEFAULT, USER, "diana", READ_EXECUTE)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, ALL)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesDefaultMaskPreserved() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "diana", ALL)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "diana", FsAction.READ_EXECUTE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "diana", READ_EXECUTE)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ_EXECUTE)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "diana", ALL)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesAccessMaskPreserved() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ)) .add(aclEntry(ACCESS, USER, "diana", READ_WRITE)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", READ)) .add(aclEntry(DEFAULT, USER, "diana", READ_WRITE)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ_WRITE)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, "diana", READ_EXECUTE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ)) .add(aclEntry(ACCESS, USER, "diana", READ_WRITE)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", READ)) .add(aclEntry(DEFAULT, USER, "diana", READ_EXECUTE)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, READ_EXECUTE)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesAutomaticDefaultUser() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, GROUP, READ_EXECUTE), aclEntry(DEFAULT, OTHER, READ)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, GROUP, READ_EXECUTE)) .add(aclEntry(DEFAULT, OTHER, READ)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesAutomaticDefaultGroup() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, READ_EXECUTE), aclEntry(DEFAULT, OTHER, READ)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, READ_EXECUTE)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, OTHER, READ)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesAutomaticDefaultOther() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, READ_EXECUTE), aclEntry(DEFAULT, GROUP, READ_EXECUTE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .add(aclEntry(DEFAULT, USER, READ_EXECUTE)) .add(aclEntry(DEFAULT, GROUP, READ_EXECUTE)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesProvidedAccessMask() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", READ_EXECUTE), aclEntry(ACCESS, MASK, ALL)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ_EXECUTE)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, ALL)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesProvidedDefaultMask() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(DEFAULT, USER, ALL), aclEntry(DEFAULT, GROUP, READ), aclEntry(DEFAULT, MASK, ALL), aclEntry(DEFAULT, OTHER, NONE)); List<AclEntry> expected = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, ALL)) .add(aclEntry(DEFAULT, OTHER, NONE)) .build(); assertEquals(expected, mergeAclEntries(existing, aclSpec)); }
@Test public void testMergeAclEntriesEmptyAclSpec() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, USER, "bruce", READ_WRITE)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, ALL)) .add(aclEntry(ACCESS, OTHER, READ)) .add(aclEntry(DEFAULT, USER, ALL)) .add(aclEntry(DEFAULT, USER, "bruce", READ_WRITE)) .add(aclEntry(DEFAULT, GROUP, READ)) .add(aclEntry(DEFAULT, MASK, ALL)) .add(aclEntry(DEFAULT, OTHER, READ)) .build(); List<AclEntry> aclSpec = Lists.newArrayList(); assertEquals(existing, mergeAclEntries(existing, aclSpec)); }
@Test(expected=AclException.class) public void testMergeAclEntriesInputTooLarge() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); mergeAclEntries(existing, ACL_SPEC_TOO_LARGE); }
@Test(expected=AclException.class) public void testMergeAclEntriesResultTooLarge() throws AclException { ImmutableList.Builder<AclEntry> aclBuilder = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)); for (int i = 1; i <= 28; ++i) { aclBuilder.add(aclEntry(ACCESS, USER, "user" + i, READ)); } aclBuilder .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, MASK, READ)) .add(aclEntry(ACCESS, OTHER, NONE)); List<AclEntry> existing = aclBuilder.build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", READ)); mergeAclEntries(existing, aclSpec); }
@Test(expected=AclException.class) public void testMergeAclEntriesDuplicateEntries() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, USER, "bruce", ALL), aclEntry(ACCESS, USER, "diana", READ_WRITE), aclEntry(ACCESS, USER, "clark", READ), aclEntry(ACCESS, USER, "bruce", READ_EXECUTE)); mergeAclEntries(existing, aclSpec); }
@Test(expected=AclException.class) public void testMergeAclEntriesNamedMask() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, MASK, "bruce", READ_EXECUTE)); mergeAclEntries(existing, aclSpec); }
@Test(expected=AclException.class) public void testMergeAclEntriesNamedOther() throws AclException { List<AclEntry> existing = new ImmutableList.Builder<AclEntry>() .add(aclEntry(ACCESS, USER, ALL)) .add(aclEntry(ACCESS, GROUP, READ)) .add(aclEntry(ACCESS, OTHER, NONE)) .build(); List<AclEntry> aclSpec = Lists.newArrayList( aclEntry(ACCESS, OTHER, "bruce", READ_EXECUTE)); mergeAclEntries(existing, aclSpec); }