Class FileAccessTree
This structure facilitates looking up files entitlements for a particular component+module combination, given that grants can occur at the directory level in addition to the individual file level.
Broadly, this class operates on strings rather than abstractions like File or Path, since those can have
behaviour that varies by platform in surprising ways; using strings makes the behaviour predictable. The strings are produced by a
method called normalizePath(java.nio.file.Path) to make sure they are absolute paths with consistent separator characters.
Internally, it does not use a tree data structure; the name "tree" refers to the tree structure of the filesystem, not the choice of
data structure. It takes advantage of the fact that, after normalization, the name of a directory containing a file is a prefix of
the file's own name. The permissions are maintained in several sorted arrays of String, and permission checks are implemented
as a binary search within these arrays.
We want the binary search to locate the relevant entry immediately, either because there's an exact match, or else because there's no exact match and the binary search points us as an entry for the containing directory. This seems straightforward if the paths are absolute and sorted, but there are several subtleties.
Firstly, there could be intervening siblings; for example, in ["/a", "/a/b"], if we look up "/a/c", the binary search
will land on "/a/b", which is not a relevant entry for "/a/c". The solution here is (1) segregate the read and write
permissions so that each array covers one homogeneous kind of permission, and (2) prune the list so redundant child entries are removed
when they are already covered by parent entries. In our example, this pruning process would produce the array ["/a"] only,
and so the binary search for "/a/c" lands on the relevant entry for the containing directory.
Secondly, the path separator (whether slash or backslash) sorts after the dot character. This means, for example, if the array contains
["/a", "/a.xml"] and we look up "/a/b" using normal string comparison, the binary search would land on "/a.xml",
which is neither an exact match nor a containing directory, and so the lookup would incorrectly report no match, even though
"/a" is in the array. To fix this, we define FileAccessTreeComparison.pathComparator() which sorts path separators
before any other character. In the example, this would cause "/a/b" to sort between "/a" and "/a.xml" so that
it correctly finds "/a".
- If an exact match exists, it will be found at the returned index
- Else, if a containing folder exists, it will be found immediately before the returned index
- Else, there is no match
- there is no match in exclusivePaths, and
- there is a match in the array corresponding to the desired operation (read or write).
Some additional care is required in the unit tests for this code, since it must also run on Windows where the separator is a
backslash and absolute paths don't start with a separator. See FileAccessTreeTests#testDuplicateExclusivePaths for an example.
-
Method Summary
Modifier and TypeMethodDescriptionbooleanbooleanbooleaninthashCode()static FileAccessTreewithoutExclusivePaths(FilesEntitlement filesEntitlement, PathLookup pathLookup, Path componentPath) A special factory method to create a FileAccessTree with no ExclusivePaths, e.g.
-
Method Details
-
withoutExclusivePaths
public static FileAccessTree withoutExclusivePaths(FilesEntitlement filesEntitlement, PathLookup pathLookup, @Nullable Path componentPath) A special factory method to create a FileAccessTree with no ExclusivePaths, e.g. for quick validation or for default file access -
canRead
-
canWrite
-
equals
-
hashCode
public int hashCode()
-