Class JsonFileNames
<table directory>/<id>.json, and
the rules an id must meet before an insert creates that file (question 12 A of the Phase 20.4
decisions). Every path the JSON backend builds from an id goes through
entityFile(Path, String), which refuses any result that is not exactly a file named
<id>.json directly in the table directory, whatever the file system's path parser made of
the name.
Refused on every operating system (creationRefusal(Path, String)), because a
common file system cannot hold the name, or Windows treats it as something else:
- a Windows device name (
CON,PRN,AUX,NUL,COM1-COM9,LPT1-LPT9, andCOMorLPTfollowed by a superscript one, two or three, in any letter case), with or without an extension: the part before the first dot is checked, sincecon.jsonis still the console device on Windows (the rule of sanitize-filename, filename-reserved-regex and Mercurial's store encoding); - a name ending in a dot or a space, which Windows drops;
.and..;- a control character (U+0000-U+001F, U+007F), a slash or a backslash (Git's
check-ref-formatand pathvalidate's universal rules); - a file name
<id>.jsonlonger than 255 bytes in UTF-8, the limit of ext4, NTFS and APFS.
Path.resolve(String) cannot turn into a path, or turns into a path other than
<table directory>/<id>.json. On Windows that is a name holding < > : " | ? *,
including one that starts with a letter and a colon (c:foo, p:<uuid>), which
Windows reads as a drive prefix instead of rejecting; on Linux : stays accepted, so
UltiRemoteBag's <uuid>:<page> ids keep working there. A JSON data folder created on
Linux with such ids cannot be copied to Windows.
These rules apply only when an insert creates a new id. A file that already exists is never renamed or rewritten because of them: it loads, and updates and deletes of its id keep working.
- Since:
- 6.3.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static interfaceResolves a file name against a directory; replaceable in tests. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final JsonFileNames.ResolverThe default resolution: the file system of the table directory decides.(package private) static final StringThe extension of every entity file.(package private) static final intThe longest entity file name accepted at insert, in UTF-8 bytes.private static JsonFileNames.ResolverTest seam: how a file name is resolved against a table directory.private static final PatternWindows device names, matched against the upper-cased part of an id before its first dot. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescription(package private) static StringcreationRefusal(Path tableDirectory, String key) Why an insert may not create the entity file ofkeyintableDirectory, ornullif it may (see the class description for the rules).(package private) static PathentityFile(Path tableDirectory, String key) The entity file ofkeyintableDirectory.(package private) static voidinstallResolver(JsonFileNames.Resolver replacement) private static booleanisControl(char c) (package private) static void(package private) static Stringkeyas messages show it: every control character as a\uXXXXescape, so a log line never carries a raw control character.private static StringunicodeEscape(char c)
-
Field Details
-
EXTENSION
The extension of every entity file.- See Also:
-
MAX_FILE_NAME_BYTES
static final int MAX_FILE_NAME_BYTESThe longest entity file name accepted at insert, in UTF-8 bytes.- See Also:
-
WINDOWS_DEVICE_NAME
Windows device names, matched against the upper-cased part of an id before its first dot. Windows also reservesCOMandLPTfollowed by a superscript one, two or three (U+00B9, U+00B2, U+00B3). -
DEFAULT_RESOLVER
The default resolution: the file system of the table directory decides. -
resolver
Test seam: how a file name is resolved against a table directory. The default isPath.resolve(String); a test installs one that rejects names the way another operating system's file system would, and resets it afterwards.
-
-
Constructor Details
-
JsonFileNames
private JsonFileNames()
-
-
Method Details
-
entityFile
The entity file ofkeyintableDirectory.The result is checked, not trusted: its parent must be
tableDirectory(both normalized, on the same file system) and its file name must be exactly<key>.json. A path parser that does not reject a name may still reinterpret it: Windows readsc:foo.jsonas a drive-relative path, which resolves to<table>/foo.json(the file of another id) or to a file on another drive, and any parser reads a separator or a..segment as a path step. Each of these is refused here, so insert, checkpoint and recovery refuse it the same way they refuse a name the parser rejects.- Parameters:
tableDirectory- the table directorykey- the entity's key- Returns:
<tableDirectory>/<key>.json- Throws:
InvalidPathException- if the file system cannot name that file, or the name does not resolve to a file named<key>.jsondirectly intableDirectory
-
creationRefusal
Why an insert may not create the entity file ofkeyintableDirectory, ornullif it may (see the class description for the rules).- Parameters:
tableDirectory- the table directory the file would be created inkey- the new entity's key- Returns:
- the reason, phrased to follow "the id cannot name its file:", or
null
-
shown
keyas messages show it: every control character as a\uXXXXescape, so a log line never carries a raw control character.- Parameters:
key- an entity key- Returns:
- the key with its control characters escaped
-
isControl
private static boolean isControl(char c) -
unicodeEscape
-
installResolver
-
resetResolver
static void resetResolver()
-