java.lang.Object
com.ultikits.ultitools.interfaces.impl.data.json.JsonFileNames

final class JsonFileNames extends Object
The file an entity id names in a JSON table directory, <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, and COM or LPT followed by a superscript one, two or three, in any letter case), with or without an extension: the part before the first dot is checked, since con.json is 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-format and pathvalidate's universal rules);
  • a file name <id>.json longer than 255 bytes in UTF-8, the limit of ext4, NTFS and APFS.
Refused only where the server's file system rejects it: any other name that 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
  • Field Details

    • EXTENSION

      static final String EXTENSION
      The extension of every entity file.
      See Also:
    • MAX_FILE_NAME_BYTES

      static final int MAX_FILE_NAME_BYTES
      The longest entity file name accepted at insert, in UTF-8 bytes.
      See Also:
    • WINDOWS_DEVICE_NAME

      private static final Pattern WINDOWS_DEVICE_NAME
      Windows device names, matched against the upper-cased part of an id before its first dot. Windows also reserves COM and LPT followed by a superscript one, two or three (U+00B9, U+00B2, U+00B3).
    • DEFAULT_RESOLVER

      private static final JsonFileNames.Resolver DEFAULT_RESOLVER
      The default resolution: the file system of the table directory decides.
    • resolver

      private static volatile JsonFileNames.Resolver resolver
      Test seam: how a file name is resolved against a table directory. The default is Path.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

      static Path entityFile(Path tableDirectory, String key)
      The entity file of key in tableDirectory.

      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 reads c:foo.json as 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 directory
      key - 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>.json directly in tableDirectory
    • creationRefusal

      static String creationRefusal(Path tableDirectory, String key)
      Why an insert may not create the entity file of key in tableDirectory, or null if it may (see the class description for the rules).
      Parameters:
      tableDirectory - the table directory the file would be created in
      key - the new entity's key
      Returns:
      the reason, phrased to follow "the id cannot name its file:", or null
    • shown

      static String shown(String key)
      key as messages show it: every control character as a \uXXXX escape, 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

      private static String unicodeEscape(char c)
    • installResolver

      static void installResolver(JsonFileNames.Resolver replacement)
    • resetResolver

      static void resetResolver()